1.静态成员
(1)静态方法
在类中,如果成员方法的头部加入修饰符static,则该成员方法在不创建类对象的情况下也可以直接用类名来调用,这种成员方法叫作静态方法。
【代码16.1】静态方法例程1
在代码16.1中,Adder类中的add()方法用来做加法和字符串串接。如果add方法不是静态方法,要调用Adder类中的add()方法时,必须先创建Adder类的对象。而在当前这种情况下,调用Adder类中的add()方法做加法和字符串串接是和Adder类的对象无关的,没有必要创建Adder类的对象。这样,就定义add()方法为静态方法(static)。
当然,创建Adder类的对象后用对象名去调用静态方法也是可以的,但是静态方法不是针对Adder类的对象的操作,所以最好还是用类名来调用。
静态方法是可以在没有创建类的对象时就调用,而对于没有创建类的对象,成员变量没有分配空间,所以,静态方法不可以访问非静态的成员变量。
【代码16.2】静态方法例程2
在代码16.2中,main()方法是static方法,在执行main()方法的时候,还没有创建TestStatic类的对象,那么就没有给成员变量a分配过空间,在main()方法中访问a时就会编译错误。同样,go()方法是非静态方法,是要针对某个具体对象调用的,由于现在没有创建TestStatic类的对象,所以这一句也会编译错误。因此,静态方法不能访问非静态的成员。
main()方法是程序的执行入口,在调用main()方法之前没有机会创建类的对象,要使得main()方法在没有创建对象的时候就可以直接调用,main()方法必须是static的。因为main()方法是static的,所以在main()方法中不能引用当前类中非static的成员变量和成员方法。
【代码16.3】静态方法例程3
在代码16.3中,必须要先在main()方法中创建当前类的对象,然后用对象名引用其他非静态的成员变量和成员方法。
(2)静态变量
在代码16.4中,Circle类包含成员变量radius(圆的半径)、pi(π的取值)、count(圆对象计数器)。
每当创建一个Circle类的对象时,都会为该对象分配radius、pi、count的内存空间。
如果所有的圆对象采用的pi都是一样的,能不能所有的圆对象共享相同的pi空间,而不是每个圆对象都有一个pi空间呢?解决的方法就是定义pi为static成员。
如果要统计共创建了多少个圆对象,那么就不是每个对象都有一个count计数器,而是整个类有一个count计数器,所以count要定义为static成员。
【代码16.4】静态变量例程
在代码16.4中,如果所有Circle对象的成员变量pi的值都是相等的,那就可以把pi定义为静态的,意味着所有Circle类的对象都共享同一个pi空间。
Circle类中的成员变量count是用来计算对象创建个数的,每创建一个对象,就会调用一次构造方法,在构造方法中count自增1。这个计数器要想累计所有的对象个数,就不能每个对象都有一个count空间,而需要所有对象共用同一个count空间,所以count必须是static的。pi和count叫作静态成员变量,是类的所有对象共享的,又叫作类变量。
静态变量有默认初值:0(整型)、0.0(浮点类型)、false(布尔类型)、null(引用类型)。
成员变量是在创建对象的时候分配空间,但是静态成员变量不同,因为静态成员变量不是属于某个对象,是当前类的所有对象共享的,是属于这个类的。静态成员变量不是在创建对象的时候开辟空间,而是在类加载入内存的时候开辟空间,static成员变量是类的所有对象共享的。
static变量的内存分配图示如图3.16.2所示,可以看到,Circle类有两个对象c1和c2,成员变量c1.radius和c2.radius会分配各自的内存空间,而静态成员变量pi和count是类变量,是在Circle类加载入内存时创建的,是所有Circle类的对象(包括c1、c2)所共享的空间。
图3.16.2 static变量的内存分配图示