zoukankan      html  css  js  c++  java
  • 成员变量和局部变量

    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

  • 相关阅读:
    python学习第18天----属性、类方法、静态方法
    面试总结
    JAVA面试题整理
    Docker-基础
    Shell
    MYSQL
    logstash的使用(ELK)
    (ELK)FileBeat的使用
    Zookeeper的介绍和单机、集群搭建
    Elaticsearch7.7.0的安装(ELK)
  • 原文地址:https://www.cnblogs.com/gyjx2016/p/12584489.html
Copyright © 2011-2022 走看看