好吧,我承认我有赌的成分。我以为我能赌出答案,结果赌输了。
还得利用JVM的知识点进行运算。
1、考点:
- 就近原则
- 变量的分类
- 成员变量:类变量、实例变量
- 局部变量
- 非静态代码块的执行:每次执行实例对象都会执行
- 方法的调用规则:调用一次执行一次
2、局部变量和成员变量的区别
1、声明位置
- 局部变量:方法体{}中、形参、代码块{}中
- 成员变量:类中方法外
- 类变量:有static修饰
- 实例变量:没有static修饰
2、修饰符
- 局部变量:final
- 成员变量:public、protect、private、final、static、volatile、transient(序列化)
3、存储位置:
- 局部变量:栈
- 实例变量:堆
- 类变量:方法区
4、作用域
- 局部变量:从声明处开始,到所属的 } 结束
- 实例变量:在当前类中 “this.” (有时this.可以省略),在其他类中 “对象名.” 访问
- 类变量:在当前类中 “类名.” (有时类名. 可以省略),在其他类中“类名.” 或 “对象名.” 访问
5、生命周期
- 局部变量:每一个线程,每一次调用执行行都是新的生命周期
- 实例变量:随着对象的创建而初始化,随着对象的被回收而消亡,每一个对象的实例化变量是独立的
- 类变量”随着类的初始化而初始化,随着类的卸载而消亡,该类的所有对象的类变量是共享的
补充:
堆(Heap):
此内存区域的唯一目的就是存放实例对象,几乎所有的实例对象都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配
栈(Stack):
通常说的栈是指虚拟机栈**。虚拟机栈用于存储局部变量表等。局部变量表存放了编译期可知长度的各种基本数据类型(8大基本数据类型)、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址)。方法执行完,自动释放。
方法区(Method Area):
用于存储已被虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据
3、具体的测试代码
测试代码:
package pers.mobian.questions06;
public class Test01 {
static int s;//成员变量,类变量
int i;//成员变量,实例变量
int j;//成员变量,实例变量
{
int i = 1; //局部变量
i++; //局部变量 如果此处想要成为成员变量,就需要在变量前面添加一个this关键字
j++; //成员变量
s++; //成员变量
}
public void test(int j) {
j++; //局部变量 如果此处想要成为成员变量,就需要在变量前面添加一个this关键字
i++; //成员变量
s++; //成员变量
}
public static void main(String[] args) {
Test01 test01 = new Test01();
Test01 test02 = new Test01();
test01.test(10);
test01.test(20);
test02.test(30);
System.out.println(test01.i + "," + test01.j + "," + test01.s);
System.out.println(test02.i + "," + test02.j + "," + test02.s);
}
}
执行结果:
2,1,5
1,1,5
4、过程分析(重点)
Test01 test01 = new Test01();
Test01 test02 = new Test01();执行这两句以后,对应的信息变化为下图:
补充:
- 先对该类进行初始化,即会调用对应的clint方法,在方法区中为s开辟一块空间
- 实例化对象的时候,会调用对应的init方法,其中init方法由非静态实例变量显示赋值代码和非静态代码块、对应构造器代码组成
- 非静态实例变量显示赋值代码:i = 0, j = 0
- 非静态代码块:执行 {} 中的代码块(在栈中开辟一个栈帧),其中代码块中的 i 为局部变量,代码块执行完毕消失。但是 j 为成员变量,所以会进行对应的 +1 操作(就近原则),成员变量 i 结果不变。
- 对应构造器代码:此处无参构造没有任何效果,所以可以忽略
test01.test(10)
test01.test(20)
test02.test(30)执行这三行代码以后内存的分配情况,如下图:
补充:
- test01调用对应的test方法的时候,j 是局部变量所以 j 值为11,注意区分此处的 j 和堆内存中的 j 值。
- test方法中的 i 值为成员变量,所以会在堆内存中被修改为1
- test方法中的 s 值也是成员变量,并且其是static变量,所以 s 变量会在方法区中进行 +1 操作
- 再次执行test01中的test方法,重复1-3的步骤
- 执行test02对象中的test方法,i 的 +1 在堆中完成,s 的 +1 操作在方法区中完成,j 的 +1 操作在栈中完成 j = 31(由于 j 变量是局部变量,所以在执行对应的操作以后,失效)
5、补充
当局部变量与xx变量重名时,如何区分:
- 局部变量与实例变量重名
- 在实例变量前面提添加 “this.” 关键字
- 局部变量与类变量重名:
- 在类变量前面加 “类名.”
今天的文章成员变量和局部变量详解分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/12700.html