5.3成员变量和局部变量
- Java变量分:成员变量和局部变量。
- 成员变量和局部变量的运行机制存大差异
5.3.1成员变量和局部变量
- 成员变量
- 类里定义的变量
- 局部变量
- 方法里定义的变量。
- 第一个单词首字母小写,后面每个单词首字母大写。
- 类变量从该类的准备阶段起开始存在,
- 直到系统销毁这个类,类变量的作用域与这个类的生存范围相同:
- 实例变量从该类的实例被创建起开始存在
- 直到系统销毁这实例
- 实例变量的作用域与对应实例的生存范围相同
- 定义Person类,类中定义两成员变量
- 实例变量:name,类变量: eyenum
- 创Person实例,通过Person类和Person实例来访问实例变量和类变量
- 成员变量无须显式初始化,只要为一个类定义了类变量或实例变量,
- 系统就在这个类的准备阶段或创建该类的实例时进行默认初始化,
- 成员变量默认初始化时的赋值规则与
- 数组动态初始化时数组元素的赋值规则完全相同。
- 类变量的作用域比实例变量的作用域更大:
- 实例变量随实例的存在而存在,
- 类变量则随类的存在而存在。
- 实例也可访问类变量,同一个类的所有实例访问类变量时,
- 实际上访问的是该类本身的同一个变量,
- 同一片内存区。
- 局部变量如下三种
- 形参:在定义方法签名时定义的变量,形参的作用域在整个方法内有效
- 方法局部变量:
- 代码块局部变量:在代码块中定义的局部变量,这个局部变量的作用域从定义该变量的地方生效,到该代码块结束时失效
- 局部变量除形参之外,都必须显式初始化。
- 须先给方法局部变量和代码块局部变量指定初始值,否则不可访问它们。
- 只要离开了代码块局部变量所在的代码块,这个局部变量就立即被销毁,不可见
-
方法局部变量作用域从定义该变量开始,直到该方法结束
- 当通过类或对象调用某个方法时,
- 系统会在该方法栈区内为所有的形参分配内存空间,
- 并将实参的值赋给对应的形参,这就完成了形参的初始化。
- 形参的传递机制请参阅5.2.2节
- 同一类里,成员变量的作用范围是整个类内有效,
- 一个类不能定义两个同名的成员变量
- 即使一个是类变量,一个是实例变量也不
- 同一方法中不同代码块内的代码块局部变量可同名
- 如果先定义代码块局部变量,后定义方法局部变量,
- 前面定义的代码块局部变量与后面定义的方法局部变量也可同名
- Java允许局部变量和成员变量同名,
- 如果方法里的局部变量和成员变量同名,
- 局部变量会覆盖成员变量,
- 如果需要在这个方法里引用被覆盖的成员变量,
- this(对于实例变量)或类名(对于类变量)作为调用者来限定访问成员变量。
- 局部变量覆盖成员变量时,
- 依然可在方法中显式指定类名和this作为调用者来访问被覆盖的成员变量
- 尽量避免这种局部变量和成员变量同名的情形。
5.3.2成员変量的初始化和内存中的运行机制
- 当系统加载类或创建该类实例时,系统自动为成员变量分配内存空间,并在分配内存空间后,自动为成员变量指定初始值。
- Person pl= new Person();时
- 如果这行代码第一次用Person类,则系统会在第一次使用Person类时加载这个类,并初始化这个类。
- 在类的准备阶段,系统为该类的类变量分配内存空间,并指定默认初始值。
- 当Person类初始完成后,如图5.10
- 图5.10,当Person类初始化完成后,系统在堆中为Person类分配一块内存区(当Person类初始化完成后,系统为Person类创一个类对象,具体参考18章),这块内存区里含eyenum类变量的内存,并默认初始值:0。
- 系统接着创建了Person对象,并把这个Person对象赋给p1,Person对象里含名为name的实例变量,实例变量是在创建实例时分配内存空间并指定初始值的。
- 当创建了第一个 Person对象后,存储示意图如图5.11
- 图5.11中
- eyenum类变量不属于Person对象,它属于Person类,所以创建第
一个 Person对象时并不需要为 eyenum类变量分配内存,系统只为name实例变量分配了内存空间,并指定默认初始值:null
- Person p2= new Person();
- 代码创建第二个 Person对象,此时因为 Person类已经存在于堆
内存中了,所以不需对 Person类初始化。 - 创建第二个 Person对象与创建第一个 Person对象并没有什么不同。
- p1.name="张三"时,将p1的name实例变量赋值,
- 让图5.11中堆内存中的name指向”张三"字符串。
- 执行完后,示意图如图5.12
- 5.12看出,name实例变量是属于单个Person实例的
- pl.eyenum=2;时,此时通过Person对象来修改Person的类变量,
- 图5.12中,Person对象根本没保存eyenum这个变量,
- 通过p1访问的eyenum类变量,还是Person类的eyenum类变量
- 此时修改的是 Person类的 eyenum类变量
- 修改成功后,内存中的存储示意图如图5.13
- 图5.13看出,当通过p1访问类变量时,实际上访问的是Person类的 eyenum类变量
- 事实上,所有的 Person实例访问 eyenum类变量时都将访问到 Person类的 eyenum类变量,也就是图5.13中灰色覆盖的区域。
- 建议读者,当程序需要访问类变量时,尽量使用类作为主调,而不要使用对象作为主调,这样可以避免程序产生歧义,提高程序的可读性。
5.3.3局部変量的初始化和内存中的运行机制
here!!!