成员变量的初始化和内存中的运行机制
系统加载类或创建类的实例时,系统自动为成员变量分配内存空间,然后自动为成员变量指定初始值。
class Person
{
public String name; // 实例变量
public static int eyeNum; // 类变量
}
var p1 = Person();
var p2 = Person();
p1.name = "张三";
p2.name = "王五";
p1.eyeNum = 2;
p2.eyeNum = 3;
- 第7行代码,如果是第一次使用Person类,系统会加载这个类并初始化这个类,即为该类的类变量分配内存空间,并指定默认值。
- 在加载类之后,第7行实际上还创建了一个Person对象(实例),并让引用变量
p1
指向它。这时,p1指向的对象中,name这个实例变量默认初始化为null
。
- 第8行代码,此时并不是第一次加载Person类,不会再次分配eyeNum的内存。只是让
p2
指向一个新的Person对象。
- 第10行代码,这时为p1的实例变量
p1.name
赋值。这个操作实际上是让name指向一个字符串(还记得字符串的内存运行机制吗?)
尽量使用类来调用类变量。虽然Java允许使用对象来调用类变量,但这太容易造成误会了。没必要非考验自己的智商。
局部变量的初始化和内存运行机制
- 局部变量不会自动初始化,因此除非被显式赋值,不然不会为它分配内存;
- 局部变量不属于任何类或实例,因此总是位于栈内存中,具体地:
- 如果是基本类型的变量,就直接把该变量的值存在栈内存中;
- 如果是引用类型的变量,栈内存中存的是地址,通过该地址指向实际的对象或数组。
栈内存中的变量不需要系统垃圾回收,往往随着方法或代码块的结束而结束
对引用类型的局部变量,方法或代码块结束时,它销毁。此时堆中的对象或数组没有人指向它了。若没有任何引用变量指向它,会启动垃圾回收机制,销毁堆内存中的它。