Java中參數傳遞是值傳遞,還是引用傳遞的一次深究


 Java中參數傳遞是值傳遞,還是引用傳遞的一次深究

是我自己分析的,可能不準確,請大牛們指導,歡迎大家拍磚

1 先回顧一下java基礎內容:對象在內存分配方式

public static void main(String[] args)
{
    Person p = new Person();
}


 這一句"Person p = new Person();" 分配了兩個對象.
 一個是引用對象p分配在棧中,
 一個是實體對象new Person(),分配在堆上

並且p保存了實體對象的地址

 如下圖所示

 棧內存                                                                                  堆內存

 引用對象p指向了 一個實體對象 Person.
  對於堆上和棧上分配內存的釋放,有java基礎的人都知道,在這裏就不說了。不知道可以百度。
 

 2 函數中參數傳遞的兩種類型 
   2.1  參數類型爲基本類型  如 int float 等等
   基本類型傳遞舉例

public class PersonDemo
{ 
 public static void main(String[] args)
 {
  int n =100;
  System.out.println(n);
  changeN(n);
  System.out.println(n);
 }
 
 public static int changeN(int a)
 {
  return a = a+1;
 }
}


相信大家都知道結果:
   100
   100
   從這裏,我們都可以看出java中方法的參數傳遞是按值傳遞的。


   2.2   參數類型爲對象類型 如Person
   例子一

public class PersonDemo
{
  public static void main(String[] args)
  {
   Person p = new Person();
   p.age = 10;
   System.out.println("傳遞前age=" +p.age);
   changeAge(p);
   System.out.println("傳遞後age=" +p.age);
  }
  public static int changeN(int a)
  {
   return a = a+1;
  }
  public static void changeAge(Person per)
  {
   per.age += 10;
  }
}

 class Person  
 {
  int age;
 }

 

輸出結果:
 傳遞前age=10
 傳遞後age=20
 可能有人會想 例子一這裏傳遞的是對象的引用。

例子二

public class PersonDemo
 {
  public static void main(String[] args)
  {
   Person p = new Person();
   p.age = 10;
   System.out.println("傳遞前age=" +p.age);
   changePerson(p);
   System.out.println("傳遞後age=" +p.age);
  } 
  public static int changeN(int a)
  {
   return a = a+1;
  }
  public static void changeAge(Person per)
  {
   per.age += 10;
  }  
  public static void changePerson(Person per)
  {
   Person p1 = new Person();
   p1.age = 50;
   per =p1;
  }
 }
 class Person  
 {
  int age;
 }



  輸出結果
  傳遞前age=10
  傳遞後age=10 
  可能有人會想 例子二中這裏傳遞的是對象的引用的一個複製。
  對於例子二我想了一個圖示

對於第二種參數傳入類型爲對象的情況,解釋有3種
  說法1 參數是按引用傳遞的,對於說法1 還有兩種解釋,
  解釋1 引用傳遞時是傳入對象的引用
  解釋2 引用傳遞時是傳入對象引用的複製
  說法2 參數是按值傳遞

  到底關於對象類型的參數,java中是按什麼傳遞的,
  其實java中不管是對象參數還是基本類型參數,都是按值傳遞的。

我們可以對方法中參數某些值進行打印 比如 Hashcode
  這是部分代碼 Person類可以參考上面定義的。
 

public class PersonDemo
 {
  
  public static void main(String[] args)
  {
   Person p = new Person();
   System.out.println("傳遞前hascode=" +p.hashCode());
   hc(p);
  }
  
  public static void hc(Person per)
  {
   System.out.println("傳遞後hascode=" +per.hashCode());
  }
 }


 

輸出結果
 傳遞前hascode=29855319
    傳遞後hascode=29855319
 我們可以看出 參數中傳遞進來的對象的hashcode和參數外面的一樣。
 我們再看一個例子

 public class PersonDemo
 {
  static Person CP = new Person();
  public static void main(String[] args)
  {
   equalPer(CP);
  }
  
  public static void equalPer(Person per)
  {
   System.out.println("比較對象結果:" +(per == CP));
  }
 }


輸出結果
 比較對象結果:true
 用==進行比較, 我們一直都認爲是比較的值相等,而不是內容。
 查看JDK文檔中隊 hashcode方法的描述,有這麼一段話
   實際上,由 Object 類定義的 hashCode 方法確實會針對不同的對象返回不同的整數。
 這一般是通過將該對象的內部地址轉換成一個整數來實現的,但是 JavaTM 編程語言不需要這種實現技巧。)
 通過上面的分析,關於對象傳遞,傳遞的是對象的一個引用(這裏的引用跟c++中的引用不是一回事),這裏的引用對象
 是"該對象的內部地址轉換成一個整數" ,其實就是一個整數。
 所以我們可以肯定了java中不管是對象參數還是基本類型參數,都是按值傳遞的。 
 
 附帶說明:
 c++裏面關於對象的一些知識
  c++也是面向對象的語言,c++裏面建立對象的方法是 :Person * p1 = new Person;
  new出來返回的是一個對象的指針,java中沒有指針這個說法。
  而這個棧上的指針p也是指向堆上的new Person對象。
  貌似跟java很類似,的確很類似 如果你在c++中也實現類似的改變Person中age的方法

 public  void changeAge(Person * p)
  {
  p->age += 10;
  }

 他也改變 Person中age的值。他傳入的是一個指針類型,從這個角度可以看出,C++中傳遞是按值傳遞的。


  C++中按引用傳遞的方式是這樣的

  public  void changeAge(Person & p)
  {
  p.age += 10;
  }


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章