java值传递(参数为对象)分析

java代码

package com.test;

public class User {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

package com.test;

public class TestMain {

    public static void main(String[] args) {
        User user = new User();
        user.setName("abc");
        test(user);
        System.out.println(user.getName());
    }

    public static void test(User user){
        user = new User();
        user.setName("efsdf");
    }
}
输出结果:
abc
package com.test;

public class TestMain {

    public static void main(String[] args) {
        User user = new User();
        user.setName("abc");
        test(user);
        System.out.println(user.getName());
    }

    public static void test(User user){
        user.setName("efsdf");
    }
}
输出结果:
dfsdf

反汇编代码

Compiled from "TestMain.java"
public class com.test.TestMain {
  public com.test.TestMain();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
        // new创建对象,将对象引用地址放到棧顶 
       0: new           #2                  // class com/test/User
       // 复制一份压棧
       3: dup
       4: invokespecial #3                  // Method com/test/User."<init>":()V
       // 棧顶元素放到局部变量表中索引为1,即存的是user地址,出棧
       7: astore_1
       // 将1号局部变量及user地址,压棧
       8: aload_1
       // 压棧
       9: ldc           #4                  // String abc
       // 调用实例方法
      11: invokevirtual #5                  // Method com/test/User.setName:(Ljava/lang/String;)V
      // 将1号局部变量及user地址,压棧
      14: aload_1
      // 调用静态方法,将棧顶元素传入user地址
      15: invokestatic  #6                  // Method test:(Lcom/test/User;)V
      18: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
      // 此时局部变量表未进行任何改变,指向老user
      21: aload_1
      22: invokevirtual #8                  // Method com/test/User.getName:()Ljava/lang/String;
      25: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      28: return

  public static void test(com.test.User);
    Code:
        // 创建user
       0: new           #2                  // class com/test/User
       // 复制新地址入棧
       3: dup
       4: invokespecial #3                  // Method com/test/User."<init>":()V
       // 新user地址存入局部变量表
       7: astore_0
       8: aload_0
       9: ldc           #10                 // String efsdf
      // 此时棧顶为新的对象地址,所以改变的是新地址指向对象的空间
      11: invokevirtual #5                  // Method com/test/User.setName:(Ljava/lang/String;)V
      14: return
}

去掉newUser()步骤反汇编代码为

public class com.test.TestMain {
  public com.test.TestMain();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class com/test/User
       3: dup
       4: invokespecial #3                  // Method com/test/User."<init>":()V
       7: astore_1
       8: aload_1
       9: ldc           #4                  // String abc
      11: invokevirtual #5                  // Method com/test/User.setName:(Ljava/lang/String;)V
      14: aload_1
      15: invokestatic  #6                  // Method test:(Lcom/test/User;)V
      18: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
      21: aload_1
      22: invokevirtual #8                  // Method com/test/User.getName:()Ljava/lang/String;
      25: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      28: return

  public static void test(com.test.User);
    Code:
       0: aload_0
       1: ldc           #10                 // String efsdf
       3: invokevirtual #5                  // Method com/test/User.setName:(Ljava/lang/String;)V
       6: return
}

发现只是差了test方法中的new的操作,即

0: new           #2                  // class com/test/User
3: dup
4: invokespecial #3                  // Method com/test/User."<init>":()V
7: astore_0

结论:new User()的test方法棧顶部的为新的user对象的地址,而astore_0将局部变量表中的地址也就是user的地址在局部变量表中进行更改,实际对原对象的内容没有进行更改,而外部输出采用的是外部函数棧帧的局部变量表,并未进行更改,指向还是原对象的堆内存(即,user= new User()就是对内部函数局部变量表进行赋值,对外部没啥影响)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值