天天看點

Java是值傳遞還是引用傳遞

觀點:Java沒有引用傳遞,隻有值傳遞

基本概念

  • 實參:實際參數,是提前準備好并指派完成的變量。配置設定到棧上。如果是基本類型直接配置設定到棧上,如果是引用類型,棧上配置設定引用空間存儲指向堆上配置設定的對象本身的指針。String等基本類型的封裝類型比較特殊,後續讨論。
  • 形參:形式參數,方法調用時在棧上配置設定的實參的拷貝。
  • 值傳遞:方法調用時,實際參數把它的值傳遞給對應的形式參數,形參接收的是原始值的一個拷貝,此時記憶體中存在兩個相等的變量
  • 引用傳遞:方法調用時将實參的位址傳遞給對應的形參,實參和形參指向相同的内容

Java資料有兩個類型

  • 基本類型
  • 引用類型

Java是值傳遞還是引用傳遞

如上圖所示,基本類型傳遞時,線程在棧上配置設定形式參數并拷貝實際參數的值。

/**      * Create with IntelliJ IDEA      * Author               : wangzhenpeng      * Date                 : 2018/4/8      * Time                 : 上午9:48      * E-mail               : [email protected]      * Description          : Test      */     public class Test {         public static void main(String[] args) {             int value = 100;             change(value);             System.out.println("outer: " +  value);         }         static void change(int value) {             value = 200;             System.out.println("inner: " +  value);         }     }           

結果輸出:

inner: 200     outer: 100           

方法修改的隻是形式參數,對實際參數沒有作用。方法調用結束後形式參數随着棧幀回收。

Java是值傳遞還是引用傳遞

如上圖所示,引用類型傳遞時,傳遞的是引用的值,從這個角度來講還是值傳遞。如果是引用傳遞的話,傳遞的應該是引用的位址,而不是引用的值。

/**      * Create with IntelliJ IDEA      * Author               : wangzhenpeng      * Date                 : 2018/4/8      * Time                 : 上午9:48      * E-mail               : [email protected]      * Description          : Test      */     public class Test {         public static void main(String[] args) {             Person person = new Person();             person.setAge(17);             person.setName("Tom");             change(person);             System.out.println("outer: " +  person.getAge());         }         static void change(Person value) {             value.setAge(18);             System.out.println("inner: " +  value.getAge());         }         static class Person {             private String name;             private Integer age;             public String getName() {                 return name;             }             public void setName(String name) {                 this.name = name;             }             public Integer getAge() {                 return age;             }             public void setAge(Integer age) {                 this.age = age;             }         }     }           
inner: 18     outer: 18           

方法修改的是引用所指向的資料空間的資料,是以方法外部也能看到修改的結果。

基本類型的數組也是對象,是以int[] 傳遞的也是對象應用的值。

/**      * Create with IntelliJ IDEA      * Author               : wangzhenpeng      * Date                 : 2018/4/8      * Time                 : 上午9:48      * E-mail               : [email protected]      * Description          : Test      */     public class Test {         public static void main(String[] args) {             int[] intArray = new int[10];             change(intArray);             System.out.println("outer: " +  intArray[0]);         }         static void change(int[] value) {             value[0] = 200;             System.out.println("inner: " +  value[0]);         }     }           

運作結果:

inner: 200     outer: 200           

如果對引用類型的傳遞稍作修改

static void change(Person value) {             value = new Person();             value.setAge(18);             System.out.println("inner: " +  value.getAge());         }           
inner: 18     outer: 17           

用圖解釋為:

Java是值傳遞還是引用傳遞

同理String,Integer等類型的封裝類型為final類型,對資料的修改操作實際上是建立了一個新的對象

/**      * Create with IntelliJ IDEA      * Author               : wangzhenpeng      * Date                 : 2018/4/8      * Time                 : 上午9:48      * E-mail               : [email protected]      * Description          : Test      */     public class Test {         public static void main(String[] args) {             String value = "123";             change(value);             System.out.println("outer: " + value);         }         static void change(String value) {             value = "abc";             System.out.println("inner: " +  value);         }     }           
inner: abc     outer: 123