从内存分析局部变量与成员变量的区别 (Java)
int i;
int j;
{
int i = 1;
i++;
j++;
s++;
}
public void test(int j){
i++;
j++;
s++;
}
public static void main(String[] args){
Test T1 = new Test();
Test T2 = new Test();
T1.test(10);
T1.test(20);
T2.test(30);
System.out.println(T1.i + "," + T1.j + "," + T1.s);
System.out.println(T2.i + "," + T2.j + "," + T2.s);
}
}
答案如下:
2,1,5
1,1,5
如果是一眼就看破答案的大佬,大可出门右转,小弟就不耽误大佬的时间了,接下来就深入研究此题
一、考点
====
就近原则
变量分类
* 成员变量:类变量、实例变量
* 局部变量
非静态代码块的执行:每次创建实例对象都会执行
方法的调用规则:调用一次执行一次
二、分析
====
1、局部变量与成员变量的区别
【1】声明的位置
局部变量:方法体{}中,形参,代码块{}中
成员变量:类中方法外
类变量:有 static 修饰
实例变量:没有 static 修饰
在本题目中,局部变量有:
第 6 行非静态代码块的局部变量 i
第 11 行形参局部变量 j
第 16 行形参局部变量 args
第 17/18 行局部变量 T1,T2
成员变量有:
第 2 行的类成员变量 s
第 3,4 行的实例成员变量 i,j
【2】修饰符
局部变量:final
成员变量:public、protected、private、final、static、volatile、transient
【3】存储位置
局部变量:栈
实例变量:堆
类变量:方法区
【4】作用域
局部变量:从声明处开始,到所属的 “}” 结束
实例变量:在当前类中“this.”访问,在其他类中“对象名.”访问
类变量:在当前类中“类名.”访问,在其他类中“类名.”访问
这里注意:在本题中,第 7 行如果是 this.i++,那么就是实例成员变量自增,i++ 则表示的是 i = 1 的自增(就近原则)
【5】生命周期
局部变量:每一个线程每次调用执行都是新的生命周期
实例变量:随着对象的创建而初始化,随着对象的被回收而消亡,每一个对象的实例变量都是独立的
类变量:随着类的初始化而初始化,随着类的卸载而消亡,该类的所有对象的类变量都是共享的
2、代码分析
咱们一行行的来执行分析,看看在内存中是如何运行的,首先从 main 开始,在栈中给 main 方法分配了一块空间,进入第一行:
【1】Test T1 = new Test()
Test T1:由于 T1 是局部变量,便在分配给 main 方法的栈中分配一块空间给 T1,同时在方法区开辟了一块空间存放类信息,也就是 Test.class,加载静态变量 s,初始化为 0
new Test():在堆中开辟了一块空间存放实例对象,而具体存放的是什么,就要看实例化过程中实例变量了
实例化:实例化的过程其实是在底层执行了 <init>() 方法,实例化方法其实是有实例变量、非静态代码块,构造器等组成的
1. 实例变量存储:从实例变量可以看出,实例对象空间里面存放的是 i 和 j 两个变量,默认值为 0,也就是第 3,4 行的两个变量
2. 非静态代码块的执行:也就是第 5~10 行非静态代码块的执行,会在分配给 main 方法的栈中分配一块空间给非静态代码块,里面存储了局部变量 i,初始化为 1,i++后值为 2;由于 j 是成员变量,而 j 默认值为 0,所以 j++ 后值为 2
;s 由于是共享的,所以每次执行都会 +1,执行后值为 1
释放资源:执行完后,栈的资源便释放,非静态代码块中的 i 又变为 0(T1.j 是成员变量,不释放,值为 1;静态变量共享,不释放,值为 1)
执行后:T1.i = 0,T1.j = 1,s = 1
【2】?Test T2 = new Test()
这一步和上一步执行的是一样,不同的是静态变量 s 值 +1,执行后值为 2
执行后:T2.i = 0,T2.j = 1,s = 2
【3】T1.test(10)
T1.test():
1. 在栈中开辟了一块空间存放 T1.test() 方法
2. 在存放T1.test() 方法的空间里面开辟一块空间存放局部变量 j,初始值为 10
test() 方法执行:
1. j++:局部变量自增,执行后值为 11
2. i++:就近原则,i 会去找成员变量,由于之前成员变量 i 默认初始化为 0,所以自增后值为 1
3. s++:s 由于是共享的,所以每次执行都会 +1,执行后值为 3
资源释放:执行完后,栈的资源便释放,test() 方法中的 j?又变为 0,而 i 是成员变量,不释放,值为 1,静态变量共享,不释放,值为 3(此时成员变量 T1.j 值为 1)
执行后:T1.i = 1,T1.j = 1,s = 3
【4】?T1.test(20)
这一步和上一步执行的是一样,执行 test() 方法,局部变量 j、成员变量 i、静态变量 s 都自增加 1;释放时,局部变量 j 释放,成员变量 T1.i 自增加 1,值为 2,静态变量 s 值 +1,执行后值为 4(此时成员变量 T1.j 值为 1)
执行后:T1.i = 2,T1.j = 1,s = 4
【5】T2.test(30)
这一步和上一步执行的是一样,执行 test() 方法,局部变量 j、成员变量 i、静态变量 s 都自增加 1;释放时,局部变量 j 释放,成员变量 T2.i 自增加 1,值为 1,静态变量 s 值 +1,执行后值为 5(此时成员变量 T2.j 值为 1)
评论