【Java基礎】基本類型的包裝類作為參數傳遞是值傳遞還是引用傳遞


突然想到這個問題,然后做了下實驗,下面以Integer來講解,其他的忽略:

import java.util.Iterator;

/**
 * Created by lili on 15/9/24.
 */
public class TestNew {
    public static void main(String args[]){

        Integer i1 = 10;
        Integer i2 = 20;
        System.out.println(i1   + "   " + i2);
        change(i1,i2);
        System.out.println(i1   + "   " + i2);

        String s1 = new String("s1");
        String s2 = new String("s2");
        System.out.println(s1 + "   " + s2);
        change(s1, s2);
        System.out.println(s1   + "   " + s2);

        StringBuilder sb1 = new StringBuilder("sb1");
        StringBuilder sb2 = new StringBuilder("sb2");
        System.out.println(sb1   + "   " + sb2);
        change(sb1,sb2);
        System.out.println(sb1   + "   " + sb2);

    }

    public static void change(Integer i1, Integer i2){
        i1 = 100;
        i2 = 200;
    }

    public static void change(String i1, String i2){
        i1 = "ii1";
        i2 = "i22";
    }

    public static void change(StringBuilder i1, StringBuilder i2){
        i1.append("sbsbsb1");
        i2.append("sbsbsb2");
    }
}

運行結果:

10   20
10   20
s1   s2
s1   s2
sb1   sb2
sb1sbsbsb1   sb2sbsbsb2

Process finished with exit code 0

 

事實證明,只有StringBuilder是引用傳遞,其他的還是值傳遞。

按照常理,應該傳遞的是對象的地址,難道這里是因為做了自動裝箱和拆箱,編譯器幫你做了這個導致最后是值傳遞了?

帶着這個問題首先去看了class文件的反編譯代碼:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

public class TestNew {
    public TestNew() {
    }

    public static void main(String[] var0) {
        Integer var1 = Integer.valueOf(10);
        Integer var2 = Integer.valueOf(20);
        System.out.println(var1 + "   " + var2);
        change(var1, var2);
        System.out.println(var1 + "   " + var2);
        String var3 = new String("s1");
        String var4 = new String("s2");
        System.out.println(var3 + "   " + var4);
        change(var3, var4);
        System.out.println(var3 + "   " + var4);
        StringBuilder var5 = new StringBuilder("sb1");
        StringBuilder var6 = new StringBuilder("sb2");
        System.out.println(var5 + "   " + var6);
        change(var5, var6);
        System.out.println(var5 + "   " + var6);
    }

    public static void change(Integer var0, Integer var1) {
        var0 = Integer.valueOf(100);
        var1 = Integer.valueOf(200);
    }

    public static void change(String var0, String var1) {
        var0 = "ii1";
        var1 = "i22";
    }

    public static void change(StringBuilder var0, StringBuilder var1) {
        var0.append("sbsbsb1");
        var1.append("sbsbsb2");
    }
}

源代碼顯示並沒有做值傳遞的優化,因為如果做了,應該change中的參數會改為int,這樣一來Integer對象會自動拆裝為int進行值傳遞,一種自動裝卸拆箱的代碼示例如下:

 Integer integer = 11;
 integer += 9;

 /*
 Integer integer = Integer.valueOf(11);//自動裝箱
 integer = Integer.valueOf((integer.intValue() + 9));//自動拆箱再裝箱
  */

那究竟是什么原因呢?

帶着這個問題,對程序進行了debug,看看傳遞的是否是對象地址。

進入change方法后,看地址的變化

發現傳入的是地址值,change參數的i1和i2的對象指向Integer@417和Integer@418,說明指向和傳入參數的同一個對象,傳入的是地址。

接着執行方法change程序:

執行改變i1的值時,此時i1指向的對象改為了Integer@427,至此可以充分說明不是自動裝箱和拆箱的問題了,但是究其原因,我的理解還是和這個相關,因為執行到這一步的時候是i1 = 100;但是具體編譯器優化后做了自動裝箱處理,var0 = Integer.valueOf(100);所以i1指向了Integer.valueOf(100)這個新產生的對象,所以最后和值傳遞的效果一樣,不會改變調用該方法的參數的值。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM