写点什么

从内存分析局部变量与成员变量的区别 (Java)

  • 2021 年 11 月 11 日
  • 本文字数:1932 字

    阅读完需:约 6 分钟

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()


  1. Test T1:由于 T1 是局部变量,便在分配给 main 方法的栈中分配一块空间给 T1,同时在方法区开辟了一块空间存放类信息,也就是 Test.class,加载静态变量 s,初始化为 0


  1. new Test():在堆中开辟了一块空间存放实例对象,而具体存放的是什么,就要看实例化过程中实例变量了


  1. 实例化:实例化的过程其实是在底层执行了 <init>() 方法,实例化方法其实是有实例变量、非静态代码块,构造器等组成的


1.  实例变量存储:从实例变量可以看出,实例对象空间里面存放的是 i 和 j 两个变量,默认值为 0,也就是第 3,4 行的两个变量


2.  非静态代码块的执行:也就是第 5~10 行非静态代码块的执行,会在分配给 main 方法的栈中分配一块空间给非静态代码块,里面存储了局部变量 i,初始化为 1,i++后值为 2;由于 j 是成员变量,而 j 默认值为 0,所以 j++ 后值为 2


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


;s 由于是共享的,所以每次执行都会 +1,执行后值为 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)


  1. T1.test():


1.  在栈中开辟了一块空间存放 T1.test() 方法


2.  在存放T1.test() 方法的空间里面开辟一块空间存放局部变量 j,初始值为 10


  1. test() 方法执行:


1.  j++:局部变量自增,执行后值为 11


2.  i++:就近原则,i 会去找成员变量,由于之前成员变量 i 默认初始化为 0,所以自增后值为 1


3.  s++:s 由于是共享的,所以每次执行都会 +1,执行后值为 3


  1. 资源释放:执行完后,栈的资源便释放,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)


评论

发布
暂无评论
从内存分析局部变量与成员变量的区别(Java)