使用static 修饰的成员变量是类变量,属于该类本身;没有使用static 修饰的成员变量是实例变量,属于该类的实例。在同一个 JVM内,每个类只对应一个Class对象,但每个类可以创建多个Java对象。
由于同一个JVM内每个类只对应一个Class对象,因此同一个JVM内的一个类的类变量只需一块内存空间;但对于实例变量而言,该类每创建一次实例,就需要为实例变量分配一块内存空间。也就是说,程序中有几个实例,实例变量就需要几块内存空间。 下面程序可以很好地表现出实例变量属于对象,而类变量属于类的特性。
class Person { String name; int age; static int eyeNum; public void info() { System.out.println("我的名字是:" + name + ", 我的年龄是:" + age); } } public class FieldTest { public static void main(String[] args) { //类变量属于该类本身,只要该类初始化完成,程序即可使用类变量 Person.eyeNum = 2; //① //通过 Person 类访问 eyeNum类变量 System.out.println("Person 的 eyeNum 属性:" + Person.eyeNum); //创建第1个 Person 对象 Person p = new Person(); p.name = "猪八戒"; p.age = 300; //通过 p访问 Person 类的 eyeNum类变量 System.out.println("通过p变量访问 eyeNum 类变量:" + p.eyeNum); //② p.info(); //创建第2个 Person 对象 Person p2 = new Person(); p2.name = "孙悟空"; p2.age = 500; p2.info(); //通过 p2修改 Person 类的 eyeNum 类变量 p2.eyeNum = 3; //③ //分别通过p、p2和 Person 访问 Person 类的 eyeNum 类变量 System.out.println("通过 p变量访问 eyeNum 类变量:" + p.eyeNum); System.out.println("通过 p2变量访问 eyeNum类变量:" + p2.eyeNum); System.out.println("通过 Person类访问 eyeNum类变量:" + Person.eyeNum); } }
上面程序中①行代码直接对 Person 类的 eyeNum 类变量赋值。这没有任何问题,因为eyeNum类变量是属于 Person类的,当 Person类初始化完成后,eyeNum类变量也随之初始化完成。因此,程序既可对该类变量赋值,也可访问该类变量的值。
一旦 Person类初始化完成,程序即可通过 Person类访问eyeNum类变量。除此之外,Java还允许通过Person类的任意实例来访问eyeNum类变量–这是笔者认为Java设计得非常不合理的地方:既然eyeNum本质上属于 Person类,而不是属于 Person类的实例,那就应该禁止通过 Person实例来访问eyeNum类变量。
虽然 Java 允许通过 Person对象来访问 Person 类的 eyeNum类变量,但由于 Person 对象本身并没有 eyeNum类变量(只有实例变量才属于 Person 实例),因此程序通过 Person 对象来访问 eyeNum类变量时,底层依然会转换为通过 Person 访问 eyeNum类变量。也就是说,不管通过哪个 Person对象来访问eyeNum类变量,都与通过 Person类访问eyeNum类变量的效果完全相同。因此,在②行代码处通过p来访问eyeNum变量将再次输出2。
执行完②行代码时,程序创建 Person对象,系统不再为 eyeNum类变量分配内存空间,执行初始化,而只为 Person对象的实例变量执行初始化–因为实例变量才属于 Person实例,而类变量属于 Person类本身。
当 Person类初始化完成之后,类变量也随之初始化完成,以后不管程序创建多少个 Person对象,系统不再为 eyeNum类变量分配内存;但程序每创建一个 Person对象,系统将再次为name、age实例变量分配内存,并执行初始化。
当程序执行完③行代码之后,内存中再次增加了一个 Person 对象。当程序通过 p2 对eyeNum 类变量进行赋值时,实际上依然是对 Person 类的 eyeNum 类变量进行赋值。
当 Person 类的 eyeNum类变量被改变之后,程序通过 p、p2、Person 类访问 eyeNum 类变量都将输出 3。这是由于,不管通过哪个 Person 对象来访问 eyeNum类变量,底层都将转换为通过 Person 来访问 eyeNum类变量。由于 p和 p2 两个变量指向不同的 Java 对象,当通过它们访问实例变量时,程序将输出不同的结果。
转载请注明:零五宝典 » Java中的实例变量和类变量易混点(2)