古越剑箫

学习是一种习惯

  :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::
public class TestVariable {
    static int s;
    int i;
    int j;

    {
        int i = 1;
        i++;
        j++;
        s++;
    }

    public void test(int j) {
        j++;
        i++;
        s++;
    }

    public static void main(String[] args) {
        TestVariable obj1 = new TestVariable();
        TestVariable obj2 = new TestVariable();
        obj1.test(10);
        obj1.test(20);
        obj2.test(30);
        System.out.println(obj1.i + "," + obj1.j + "," + obj1.s);
        System.out.println(obj2.i + "," + obj2.j + "," + obj2.s);
    }

①声明的位置

  • 局部变量:方法体{}中,形参,代码块{}中
  • 成员变量:类中方法外
  • 类变量:有static修饰
  • 实例变量:没有static修饰

②修饰符

  • 局部变量:final
  • 成员变量:public、protected、private、final、static、volatile、transient

③值存储的位置

  • 局部变量:栈
  • 实例变量:堆
  • 类变量:方法区

④作用域

  • 局部变量:从声明处开始,到所属的}结束
  • 实例变量:在当前类中“this.”(有时this.可以缺省),在其他类中“对象名.”访问
  • 类变量:在当前类中“类名.”(有时类名.可以省略),在其他类中“类名.”或“对象名.”访问

⑤生命周期

  • 局部变量:每一个线程,每一次调用执行都是新的生命周期
  • 实例变量:随着对象的创建而初始化,随着对象的被回收而消亡,每一个对象的实例变量是独立的
  • 类变量:随着类的初始化而初始化,随着类的卸载而消亡,该类的所有对象的类变量是共享的

根据以上区别,图示展示当前变量在jvm内存中的位置

image

java中执行main方法整体流程图示如下

 

image

 

1、栈中的main方法区,内存中的局部变量ob1,obj2,指向堆中的 new TestVariable()对象,new TestVariable()在堆中存的是成员变量 int i,int j,而int s 因为是类变量所以存在了方法区中

2、new TestVariable() 无参构造的时候实际上执行<init>()方法,因此非静态代码块会执行,这个再执行都是在栈中处理

{
int i = 1;
i++;
j++;
s++;
}

所以这里的i就是局部变量,i++ 结果=1 ,j根据就近原则指向的是堆中的obj 的j  因此 obj1,obj2指向堆中的j++ 等于1 ,方法区中的类变量s++两次 这时候=2

3、obj1.test(10);实际执行代码如下

public void test(int j) {
        j++;
        i++;
        s++;
    }

 

这里的j是局部变量存在栈中,j++ 结果=11  ,i根据就近原则指向的是堆中的obj1的i,因此obj1指向堆中的i++等于1,方法区中的类变量s++1次 这时候=3

4、obj1.test(20);执行代码如下

public void test(int j) {
        j++;
        i++;
        s++;
    }

这里的j是局部变量存在栈中,j++ 结果=21  ,i根据就近原则指向的是堆中的obj1的i,因此obj1指向堆中的i++等于2,方法区中的类变量s++1次 这时候=4

5、obj2.test(30);

public void test(int j) {
        j++;
        i++;
        s++;
    }

这里的j是局部变量存在栈中,j++ 结果=31  ,i根据就近原则指向的是堆中的obj2的i,因此obj2指向堆中的i++等于1,方法区中的类变量s++1次 这时候=5

需要强调的是线程对主内存的操作(读取赋值)等必须是在自己的工作内存中,首先要将主内存的数据拷贝到自己的工作内存空间(共享变量副本),然后对变量进行操作,完成之后再将变量写到主内存中去。不能直接操作主内存的变量,各个线程中的工作内存中存储着存储着主内存的变量副本拷贝,因此不同的线程是无法访问对方工作内存,线程之间的通信(值传递)必须通过主内存来完成。

每次执行完方法当前栈中的内存就会释放

因此最后结果是 2,1,5 和  1,1,5

posted on 2020-01-28 21:28  古越剑箫  阅读(224)  评论(0编辑  收藏  举报