Java的值传递和引用传递(JVM字节码角度剖析)

Java只有值传递

大家都知道就不用多说了,Java没有引用传递,举下面一个例子

public class TestA{
    public int a ;
    public void fun1(TestA testA){
        testA.a =1000;
    }
    public static void main(String args[]){
        TestA testA = new TestA();
        testA.fun1(testA);
        System.out.println(testA.a);
    }
}

为什么结果是1000呢?对象testA的成员变量a的值为什么会变成1000?
之前的知识,知道传入方法fun1的testA是一个地址,testA.a相当于改变了地址指向的值,所以最后值为1000。

现在从jvm的角度分析一下。

  1. 首先 main方法 也是一个方法 ,所以这个方法在执行的时候就会保存在栈里面,栈里面有栈帧,栈帧里面有个局部变量表,这个时候 new TestA()的 引用 testA,就保存在 局部变量表中。

用jclasslib看一下
在这里插入图片描述
果然main方法有2个局部变量,一个是args(方法参数),一个是 testA。

testA不是基础数据类型,他是一个对象的引用,所以他在表里面保存的是一个地址,就是TestA对象实例化后 在堆中的地址

2.再用jclasslib看一下fun1 方法
在这里插入图片描述
他的局部变量表有2个参数,一个是this,这里其实解释了为什么静态方法为什么不能调用非静态的方法,因为他没有这个this参数。有了这个参数,就可以对对象的值或对象进行操作。
这里重点看第二个参数是testA,也就是显式传入的参数,这个就是上面main方法局部变量表里面变量的值。
Java只有值传递,所以传递的是值,不是testA的局部变量表中的地址
这个值 就是 对象的地址

3.最后我们看一下 fun1 的字节码文件
在这里插入图片描述

aload_1   #Load reference from local variable
sipush 1000  # Push short
putfiled    # Set field in object
  1. 第一步从局部变量表中加载 testA 这个 reference
  2. 然后把 1000这个值 push到操作数栈中
  3. putfiled 这一步最重要,看一下官方字节码解释,就是在对象中设置字段的值

我一开始认为 testA.a也是在局部变量表中保存了,但是看之前的图里面知道并没有,testA.a只是一个赋值操作。不知道java基础是怎么学的,艹。

所以我们知道了,最后就是设置了对象的值,所以值改变了

参考
java方法传递解析
Java字节码浅析(—)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值