1. 程式人生 > >理解--->Java中的值傳遞&引用傳遞

理解--->Java中的值傳遞&引用傳遞

 

轉自:https://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&mid=2247486882&idx=2&sn=0056f7c027b0db429650ea4df03985e5&chksm=ebd6328edca1bb9804927cb66bad1bb9d54e542bfea5b7ff9f9432603b919460ee601f12baf6&mpshare=1&scene=23&srcid=0113FJUlznMFE6tsTLGxjHgH#rd

值傳遞和引用傳遞

值傳遞(pass by value)是指在呼叫函式時將實際引數複製一份傳遞到函式中,這樣在函式中如果對引數進行修改,將不會影響到實際引數。

引用傳遞(pass by reference)是指在呼叫函式時將實際引數的地址直接傳遞到函式中,那麼在函式中對引數所進行的修改,將影響到實際引數,形參和實參總是指向同一個地址,形參指向哪裡實參就會指向哪裡。

java中的基本資料型別和引用資料型別

java中的基本資料型別:
  • 4種整數型別:byte、short、int、long

  • 2種浮點數型別:float、double

  • 1種字元型別:char

  • 1種布林型別:boolean

java中的引用資料型別:
  • 介面

  • 陣列

下面就對JAVA中傳遞引數是值傳遞還是引用傳遞展開討論

下面先來看基本資料型別

下面先來看基本資料型別

public class Test {
    static void testInt(int a, int b)
    {
         a=10;
         b=20;
        System。out。println("交換後 "+"a:"+a+", b:"+b);
    }    
    public static void main(String[] args)
    {
        int a=1;
        int b=2;
        System。out。println(
"交換前 "+"a:"+a+", b:"+b); testInt(a,b); System。out。println("方法結束後"+"a:"+a+", b:"+b); } }

執行結果是這樣的:

交換前:1  2

交換後:10  20

res  :  1  2

java中基本資料型別在傳遞的時候,用的是值傳遞,就是拷貝和實參一模一樣的值然後由形參進行操作,當方法結束後,形參的生命週期就會終止,實參的值並沒有受到影響。

 

下面來看引用資料型別

//  類的編寫
  class Car
  {
  public String name;
       public Car()
       {}
       public Car(String name)
       {
       this。name=name;
       }
  }
下面進行測試

public class Test
{
    public static void update1(Car car)
    {
      car。name="GTR";
      System。out。println("修改後的名字是:"+car。name);
    }
    //這個方法比上面的方法多了一條a=new Car()語句
    public static void update2(Car car)
    {
    car=new Car();
    car。name="GTR";
    System。out。println("修改後的名字是:"+car。name);
    }
    public static void main(String[] args)
    {
        Car a=new Car("AE86");
        Car b=new Car("AE86");
        System。out。println("呼叫update1前a的名字是:"+a。name);
        update1(a);
        System。out。println("呼叫update1後a的名字是:"+a。name);
        System。out。println("呼叫update2前b的名字是:"+b。name);
        update2(b);
        System。out。println("呼叫update2後b的名字是:"+b。name);

    }
}

結果:

AE86

GTR

GTR

AE86

GTR

AE86

看完上面的update1方法,覺得引用資料型別和基本資料型別不一樣,引用資料型別傳入方法後,方法呼叫結束後物件的屬性發生了變化,認為這是引用傳遞,將物件a的地址送到了形參中,然後對形參改變實參就會改變。

但是update2馬上就推翻了這個想法,將實參送入形參後,形參馬上在堆中新建了一個物件,如果是引用傳遞,那麼此時形參和實參都是指向這個物件的,然後程式又對形參的name屬性進行了修改,那麼此時實參也會被修改,看到的結果就應該和update1一樣。但是結果卻不是這樣的,並沒有修改資料,這就說明了將物件作為實參傳入方法的形參,並不是引用傳遞。

那麼java中引用型別資料到底是怎麼回事那,下面把自己的查閱資料理解的寫下來。作為後續回顧。
Car b = new Car(“AE86”);

執行這個語句首先會在棧中建立一個b變數,然後在堆中建立一個Car類的例項,然後b指向堆中的例項。

其實在java程式中,將物件傳入形參中,也是值傳遞,基本資料型別值傳遞就是拷貝一個變數的副本;下面以update2()分析,引用資料型別就是將變數名(b)指向堆的地址複製一份,也就是說在棧中有一個變數名(car)也指向堆中b的例項。

現在執行 car =new car();就是形參car指向了堆中一個新的地址,而b還是指向原來的地址的,這樣的話,car隨便修改name屬性,是影響不到b的。最後方法結束car被釋放,堆中的新物件被GC回收。

在update1()中可以修改是因為形參和實參指向同一塊內容,當形參修改name屬性,那麼堆中的物件就會被修改,update1()執行結束後,car釋放,但堆中的例項還有變數指向,不會被回收,這時就修改了b的值。