成员变量和局部变量在内存中的变化|8月更文挑战

成员变量和局部变量在内存中的变化|8月更文挑战在前边已经讲了类的加载机制,以及变量在内存中的变化,那么今天我们从成员变量和局部变量来继续加深印象,彻底弄懂成员变量和局部变量在内存中的变化

成员变量和局部变量在内存中的变化

WangScaler: 一个用心创作的作者。

声明:才疏学浅,如有错误,恳请指正。

在前边类的加载机制以及类、对象初始化的详细过程已经讲了类的加载机制,以及在Java易错点1讲解过变量在内存中的变化,那么今天我们从成员变量和局部变量来继续加深印象,彻底把知识装入脑袋中。如果你看下文不是很清楚的话,一定得先看上边的两篇文章。

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

成员变量

  • 定义在类中
  • 存在于堆内存中
  • 有默认初始值
  • 随对象的创建而创建,随对象消失而消失

局部变量

  • 定义在方法中
  • 存在于栈内存中
  • 无默认初始值
  • 方法入栈而创建,方法出栈而消失

注意:使用变量遵循就近原则,类中static修饰的变量也叫类变量。

示例代码

package com.wangscaler.variable;
​
/** * @author WangScaler * @date 2021/8/2 10:56 */public class VariableMain {
    static int i;
    int j;
    int k;
​
    {
        int j = 1;
        j++;
        i++;
        k++;
    }
​
    public void add(int j) {
        i++;
        j++;
        k++;
        
    }
​
    public static void main(String[] args) {
        VariableMain variableMain = new VariableMain();
        VariableMain variableMain1 = new VariableMain();
        variableMain.add(100);
        variableMain.add(200);
        variableMain1.add(300);
        System.out.println(variableMain.i + "--------------wangscaler------------------" + variableMain1.i);
        System.out.println(variableMain.j + "--------------wangscaler------------------" + variableMain1.j);
        System.out.println(variableMain.k + "--------------wangscaler------------------" + variableMain1.k);
    }
}

解析

先来看看这三个打印的结果是啥。

5--------------wangscaler------------------5
0--------------wangscaler------------------0
3--------------wangscaler------------------2

那么接下来看看到底是怎么执行的。

  • 1、根据类的加载机制以及类、对象初始化的详细过程我们知道main方法所在的类会先加载。

    • 加载时会先加载静态变量并赋初值。所以如果我们把main清空,不创建VariableMain对象,只打印打印i的值,会是0。

    • 我们知道jdk1.8之后,将常量池和静态变量由永久代转移至堆内存中,所以应该是下图。

image-20210802134410359.png

  • 2、创建对象variableMain

    • int j; int k;此时非静态变量会初始化

      image-20210802135417611.png

    • 代码块初始化int j = 1;,因为j在代码块中生成的,属于局部变量,固存在栈内存中。

    image-20210802135631702.png

    • j++;依据就近原则,所以此时j依然是栈内存中的j.

      image-20210802135929499.png

    • i++; k++;此时代码块没有这两个变量,那么调用的就是成员变量,所以堆内存中的i、j的值将变化。

      image-20210802140138588.png 代码块执行完毕,栈内存中的j会随着<init>调用完毕而消失,这里不再画出。

  • 3、创建对象variableMain1

    步骤基本和2相同,唯一需要注意的是,i因为是类变量是共享的,所以如为下图所示i的值会在之前值的基础上继续增加。

    image-20210802140740926.png 同样当代码块执行完毕,栈内存中的j会随着<init>调用完毕而消失,这里不再画出。

  • 4、variableMain.add(100);此时方法的调用j是形参即局部变量,根据就近原则add方法里的j都是局部变量。所以执行完之后如下图:

    image-20210802141748478.png

add方法执行完,会在栈内存中消失。

  • 5、variableMain.add(200);同上:

    image-20210802142020942.png

  • 6、variableMain1.add(300);

    image-20210802142131004.png

  • 7、结果

    根据堆内存的值,不难看出我们的结果是什么了。

注意

  • 1、类变量的调用,虽然上述的例子variableMain.i 可以正常执行,但是不建议这样写,如果你安装了代码检查的插件,他是会报错的,我们知道类变量是唯一的,所以我们调用时,应该类.变量,即VariableMain.i
  • 2、像上述的例子,因为我们j都是局部变量,所以堆内存中的j一直没变化。当局部变量和成员变量共存时,可以使用this.j来调用成员变量。
  • 3、尽量给成员变量赋初值,不要依赖编译器,上述的例子就没有赋初值。

今天的文章成员变量和局部变量在内存中的变化|8月更文挑战分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/19681.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注