從字節(jié)碼看為什么說java都是值傳遞

先上源碼

public class TestRef {

    public int id = 1;


    public static void main(String[] args) {
        int a = 10;
        String b = "a";
        TestRef c = new TestRef();

        change(a);
        change(b);
        change(c);
        changeRef(c);


    }

    public static void change(int a) {
        a = 20;
    }

    public static void change(String b) {
        b = "c";
    }

    public static void change(TestRef c) {
        c = new TestRef();
    }


    public static void changeRef(TestRef c) {
        c.id = 10;
    }
}

再上字節(jié)碼:

public class TestRef {
  public int id;

  public TestRef();
    Code:
       0: aload_0                            //將this載入棧頂
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V 
       4: aload_0                           //再次將this載入棧頂,因?yàn)樯厦婺切衖nvokespecial已經(jīng)消耗掉第一行的this去實(shí)例化對(duì)象了
       5: iconst_1                          //將常量值1推入棧頂
       6: putfield      #2                  // Field id:I  //設(shè)置偏移4那行推入的this的#2變量的值為偏移5那行所推入的值
       9: return

  public static void main(java.lang.String[]);
    Code:
       0: bipush        10
       2: istore_1
       3: ldc           #3                  // String a
       5: astore_2
       6: new           #4                  // class TestRef
       9: dup
      10: invokespecial #5                  // Method "<init>":()V
      13: astore_3
      14: iload_1
      15: invokestatic  #6                  // Method change:(I)V
      18: aload_2
      19: invokestatic  #7                  // Method change:(Ljava/lang/String;)V
      22: aload_3
      23: invokestatic  #8                  // Method change:(LTestRef;)V
      26: aload_3
      27: invokestatic  #9                  // Method changeRef:(LTestRef;)V
      30: return

  public static void change(int);
    Code:
       0: bipush        20
       2: istore_0
       3: return

  public static void change(java.lang.String);
    Code:
       0: ldc           #10                 // String c
       2: astore_0
       3: return

  public static void change(TestRef);
    Code:
       0: new           #4                  // class TestRef
       3: dup
       4: invokespecial #5                  // Method "<init>":()V
       7: astore_0
       8: return

  public static void changeRef(TestRef);
    Code:
       0: aload_0        //將參數(shù)載入棧
       1: bipush        10    //推入一個(gè)10
       3: putfield      #2                  // Field id:I  //設(shè)置參數(shù)的#2實(shí)例變量的值為10
       6: return
}

3個(gè)change(T)方法都是錯(cuò)誤的使用例子,從字節(jié)碼可以看到基本都是在操作方法自身的局部變量表,方法的參數(shù)都是一個(gè)對(duì)象引用(或者說指向?qū)ο髢?nèi)容的指針副本) 修改也只是將指針的值改變,而非指針指向的值

changeRef方法第一行就是 aload_0這個(gè)和構(gòu)造函數(shù)第一行一樣,都是將this載入棧頂
而this是一個(gè)指向?qū)ο蟮囊?指針)。
在main方法偏移26那行,aload_3 是將局部變量表slot 3 的的對(duì)象引用復(fù)制到棧頂,這樣從旁證明了,java傳遞對(duì)象的時(shí)候傳遞的是對(duì)象的引用的副本 對(duì)象的引用是4個(gè)字節(jié)(操作數(shù)棧和局部變量表 都是一個(gè)單位等于4個(gè)字節(jié) 基本類型除了 double long之外其他都是一個(gè)單位)這也從旁佐證 方法調(diào)用傳遞的是對(duì)象引用副本

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容