java 到底是值传递还是引用传递,你确定吗?

3 篇文章 0 订阅

在这里插入图片描述

简单介绍一下指令

  1. bipush 将 -128~127常量压栈
  2. ldc 数值常量或String常量值从常量池中压栈
  3. load1 将局部变量1压栈
  4. store1 抛出栈顶数据给局部变量1
  5. new 在java堆上为对象分配内存空间,并将地址压入操作数栈顶
  6. dup 复制操作数栈顶值,并将其压入栈顶,也就是说此时操作数栈上有连续相同的两个对象地址
  7. invokespecial 在这里调用 init方法 为对象初始化

第一部分

在这里插入图片描述

pp赋值p的时候 直接bipush 100 + istore_1 看着像将100 压栈 把100传递给 pp。但是我们发现 pp 和 p指向的是同一个地址。所以最终还是引用传递。同理后面a,b一样。这也说明一点 final static int p = 100原本应该直接创建在永生区的东西。因为本身就在常量池。所以jvm帮我们优化了。

第三部分

在这里插入图片描述
不管是 ldc压入字符串还是 new dup invokespecial创建obj对象地址。 c 和 d 地址一样, o 和 clone地址一样。我们可以说这里也是引用传递。

第二部分 最难理解的部分

在这里插入图片描述
跟操作字符串的指令差不多,可是最终导致 q,r,z三个int变量指向地址都不一样。
在加大难道看看
在这里插入图片描述
我们也从左边代码地址找规律,

  1. int 传 int 地址会发生变换
  2. Integer 传 Integer 地址不会发生
  3. int 传 Integer 地址会发生变化
  4. Integer 传 int 地址会发生变化

我们再从右边指令找规律

  1. int 传 int 时候 是 istore iload
  2. int 传 Integer 的时候 先调用了 Integer.valueOf()变成 Integer 再 astore aload
  3. Integer 传 int 的时候 先调用 Integer.intValue 变成 int 再 istore iload
猜测

astore aload 在字符串 和 Objec 传递的时候都用到,那么我们认为他是引用传递
istore iload 指定是值传递,但是一开始 传递100的时候也是用了这个指令。其结果是地址一致。

在这里插入图片描述
在这里插入图片描述
引用传递我们就不分析了,分析一下值传递。 先理解 不在常量池的 int值传递。 int a = 10000, int b = a; istore存值,iload获取值。因为获取到的是值,所以需要开辟一个新的地址空间去存取这个值。这没问题。 int c = 100, int d = c; istore存值,iload获取值。我们明确知道 jvm规定了这个指定是传值。也就是说 d理应需要开辟一个空间存取100。那为什么没有开辟。那只能认为是jvm做了优化。在开辟新区域存储这个100的时候,发现这个值在常量池就不创建的优化

总结

java从官网指令确实说明了 有值传递 和引用传递的概念,我们也看到了 值传递和引用传递的区别。 值传递可能需要开辟新空间去存储值,然而引用传递是不需要的。传递引用,让变量指向同一个地址空间。 但是仔细想想 不管是 int a,还是 string 他们其实都是指向一个地址。然后通过 类型截取对应数据解析。== 传给 int的时候虽然是个 值 但是最终会 变成 地址 , a 指向这个地址。传给 string时候,是地址,但是 地址也是一个值。本质上是个字节所以,所以对于变量来说是赋值传递,然而新的String变量又指向同一个对象,因此对于对象来说是引用传递。==所以我认为 弄明白这一点,java传递本质上是引用还是值不好说。,如果面试官问到可以battle一下您的新观点。

实验代码

public class CCN {

    private final static int p = 100;

    public static void main(String[] args) {
    System.out.println("p====" + System.identityHashCode(p)); //P====1198108795
        int a = 100;
        System.out.println("a====" + System.identityHashCode(a)); //a====1198108795
        int b = a;
        System.out.println("b====" + System.identityHashCode(b)); //b====1198108795

        System.out.println("**************************************");

        int q = 100000000;
        System.out.println("q====" + System.identityHashCode(q)); //q====214126413

        int r = q;
        int z = r;
        System.out.println("r====" + System.identityHashCode(r)); //r====396873410
        System.out.println("z====" + System.identityHashCode(z)); //z====1706234378
        System.out.println("**************************************");

        Integer qq = 100000000;
        System.out.println("qq====" + System.identityHashCode(qq)); //qq====1867750575
        Integer rr = qq;
        Integer zz = rr;

        System.out.println("rr====" + System.identityHashCode(rr)); //rr====1867750575
        System.out.println("zz====" + System.identityHashCode(zz)); //zz====1867750575

        System.out.println("**************************************");

        int qqq = 100000000;
        System.out.println("qqq====" + System.identityHashCode(qqq)); //qqq====2046562095
        Integer rrr = qqq;
        Integer zzz = rrr;

        System.out.println("rrr====" + System.identityHashCode(rrr)); //rrr====1342443276
        System.out.println("zzz====" + System.identityHashCode(zzz)); //zzz====1342443276

        System.out.println("**************************************");

        Integer qqqq = 100000000;
        System.out.println("qqqq====" + System.identityHashCode(qqqq)); //qqqq====769287236
        int rrrr = qqqq;
        int zzzz = rrrr;

        System.out.println("rrrr====" + System.identityHashCode(rrrr)); //rrrr====1587487668
        System.out.println("zzzz====" + System.identityHashCode(zzzz)); //zzzz====1199823423

        System.out.println("**************************************");

        String c = "abc";
        System.out.println("c====" + System.identityHashCode(c)); //c====1867750575
        String d = c;
        System.out.println("d====" + System.identityHashCode(d)); //d====1867750575

        System.out.println("**************************************");
        Object o = new Object();
        System.out.println("c====" + System.identityHashCode(o)); //o====1225358173
        Object clone = o;
        System.out.println("clone====" + System.identityHashCode(clone)); //clone====1225358173
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值