java高频面试题目记录三----成员变量与局部变量

题目和打印结果

题目资源
在这里插入图片描述

考点:

1:就近原则
2:变量的分类
(成员变量:类变量,实例变量 )
(局部变量)
3:非静态代码块的执行:在()方法中执行,即每次创建实例对象都会执行
4:方法的调用规则:调用一次执行一次

在这里插入图片描述
堆(Heap):存放对象实例(所有的对象实例以及数组都要在堆上分配)

栈(Stack):虚拟机栈,用于存储局部变量表–局部变量表存放了编译器可知长度的各种基本数据类型(boolean,int,char等),对象引用(不等同于对象,存放的是对象在堆内存的首地址)方法执行完,空间自动释放

方法区(Method Area): 用于存储已被虚拟机加载的类消息,常量,静态变量,即时编译器编译后的代码等数据

局部变量和成员变量的区别

作用域:
局部变量:从声明开始,到所属的}结束
实例变量:在当前类用this.变量名访问,在其他类中,对象名.变量名访问

生命周期:
局部变量:每一个线程,每一次调用都是新的生命周期
实例变量:随对象的创建而初始化,随对象的回收而消亡,每一个对象的实例变量是独立的。
类变量:随类的初始化而初始化(初始化过程()是由类的静态变量和类的静态代码块所组成),类的卸载而消亡,该类的所有类变量(静态变量)是共享的。

知道了上述的基本考点之后,我们来看一下,每行代码的具体运行和内存分布情况:
在这里插入图片描述
1:执行main()函数,main()所在的类首先要加载和初始化,还记得类的初始化过程吗?不清楚的可以看下我的上篇博客类的初始化过程
初始化后,静态变量int s,会在方法区中开辟空间,并初始化赋值为0
在栈中为main()方法开辟一块空间(栈中以方法为单位,分配空间)

2:然后执行第一行代码。
在栈中,main()方法块中,创建一个局部变量obj1,并在堆中,为它创建一个实例对象。还记得类的实例化过程吗?不清楚的可以看下我的上篇博客类的实例化过程
这个过程中,需要按照顺序执行非静态变量和非静态代码块。上图,圈出了非静态代码块部分,这个时候,需要在栈中,为非静态代码块开辟一段空间,放上局部变量i,根据就近原则,下一行i++,就在这里的i上操作。j++则操作当前对象obj1的成员变量j,s++,操作方法区中的S。操作过程,如上图所示。

3:main()方法中的第一行代码执行过后,栈中,非静态代码块部分空间会被释放掉。
第二行代码执行过程同上过程,就不再赘述。下面来看,第三行代码的具体运行和内存分布情况:
在这里插入图片描述
1:对于方法的调用,每创建一次,就在栈中,为该方法开辟一块空间。在test()方法空间中有一个局部变量j,并传参10
2:在test()方法中,j++,就近原则,是对test()方法空间中局部变量j操作,i++,操作对象obj1的成员变量。s++,操作方法区中的S。操作过程,如上图所示。
3:方法执行结束后,test()方法空间被释放。
后面方法的调用过程,同上,要注意,对于方法的调用,每创建一次,就在栈中,为该方法开辟一块空间。因此代码执行后的最终内存分布如下图所示:
在这里插入图片描述
因此最终的输出结果为:2,1,5,1,1,5

当局部变量与XX变量重名时,如何区分:

1:局部变量与实例变量重名----在实例变量前加this
2:局部变量与类变量重名----在类变量前加this
例如,上题我在重名变量前加this,那么就不会就近原则,操作最近的变量。
如下图所示。静态代码块中的i++,就不操作代码块中的局部变量i,而是操作当前实例的成员变量i,
例如第一行代码的执行,那么this.i++,就操作的时obj1的实例变量i。
obj1.test(10)的执行,this,j++,就操作的时obj1的实例变量j.
在这里插入图片描述

发布了18 篇原创文章 · 获赞 1 · 访问量 2302

猜你喜欢

转载自blog.csdn.net/Better_WZQ/article/details/104450130