1. 程式人生 > >java傳值還是傳引用

java傳值還是傳引用

最近一直在看primer c++,函式一章對c++函式之間傳遞引數有詳細的講解,傳值、傳指標和傳引用的應用與區別都講得很清楚,
以前一直用java,由於java沒有指標,當時也沒有引用這個概念,所以沒有對java引數的傳遞有過多的思考,現在搞清楚了c++
傳遞引數的機制,自然就會跟java進行對比,究竟java傳的是什麼東西?
Java程式碼
public static void test(Pass passA); {   
passA = null;  
}
看看, 對passA有什麼影響?
毫無作用。函式調用出來後,passA還是原來的值,不會變成Null.

但是,你的程式碼對 passA進行了操作  passA.a ,改變了passA的成員變數。
這個成員變數是一個真實指向String 的 地址,當然能夠被改變。
這就是操作 (.)  和 賦值 (=) 的區別。
這是對 成員變數 a 的 賦值。真正改變了成員變數 a 的值。

注意,這裡傳遞的引數是 passA, 而不是 a.
所以,passA 被複制了一份。passA 的這個副本的 a 變數還 指向 原來的 passA 的 a 變數。
Java中的“引用”是指非原生型別的變數的值儲存的是對一個堆上物件的引用。
Java任何時候都是傳值的,只不過該值的語義有所不同罷了

1、物件是按引用傳遞的
2、Java 應用程式有且僅有的一種引數傳遞機制,即按值傳遞
3、按值傳遞意味著當將一個引數傳遞給一個函式時,函式接收的是原始值的一個副本
4、按引用傳遞意味著當將一個引數傳遞給一個函式時,函式接收的是原始值的記憶體地址,而不是值的副本
寫的沒錯,但是文字太多,第二條就已經把人弄糊塗了,得仔細看完4條才清楚。而且對String型別的疑惑沒有解決。

三句話總結一下:

1.物件就是傳引用

2.原始型別就是傳值

3.String型別因為沒有提供自身修改的函式,每次操作都是新生成一個String物件,所以要特殊對待。可以認為是傳值。
在網上查了一下,還是外國人解釋得比較清楚:
Does Java pass by reference or pass by value?
Why can't you swap in Java?
By Tony Sintes, JavaWorld.com, 05/26/00
Q:If Java uses the pass-by reference, why won't a swap function work?
A:Your question demonstrates a common error made by Java language newcomers. Indeed, even seasoned veterans find it difficult to keep the terms straight.

Java does manipulate objects by reference, and all object variables are references. However, Java doesn't pass method arguments by reference; it passes them by value.

Take the badSwap() method for example:

Java程式碼
public void badSwap(int var1, int var2)  
 
 int temp = var1;  
 var1 = var2;  
 var2 = temp;  

 public void badSwap(int var1, int var2)
{
  int temp = var1;
  var1 = var2;
  var2 = temp;
}

When badSwap() returns, the variables passed as arguments will still hold their original values. The method will also fail if we change the arguments type from int to Object, since Java passes object references by value as well. Now, here is where it gets tricky:

Java程式碼
 public void tricky(Point arg1, Point arg2)  
{  
  arg1.x = 100;  
  arg1.y = 100;  
  Point temp = arg1;  
  arg1 = arg2;  
  arg2 = temp;  
}  
public static void main(String [] args)  
{  
  Point pnt1 = new Point(0,0);  
  Point pnt2 = new Point(0,0);  
  System.out.println("X: " + pnt1.x + " Y: " +pnt1.y);   
  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);  
  System.out.println(" ");  
  tricky(pnt1,pnt2);  
  System.out.println("X: " + pnt1.x + " Y:" + pnt1.y);   
  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);    
}  
 
                    

 public void tricky(Point arg1, Point arg2)
{
  arg1.x = 100;
  arg1.y = 100;
  Point temp = arg1;
  arg1 = arg2;
  arg2 = temp;
}
public static void main(String [] args)
{
  Point pnt1 = new Point(0,0);
  Point pnt2 = new Point(0,0);
  System.out.println("X: " + pnt1.x + " Y: " +pnt1.y);
  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
  System.out.println(" ");
  tricky(pnt1,pnt2);
  System.out.println("X: " + pnt1.x + " Y:" + pnt1.y);
  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y); 
}

                    If we execute this main() method, we see the following output:

Java程式碼
 X: 0 Y: 0 
X: 0 Y: 0 
X: 100 Y: 100 
X: 0 Y: 0 

 X: 0 Y: 0
X: 0 Y: 0
X: 100 Y: 100
X: 0 Y: 0 The method successfully alters the value of pnt1, even though it is passed by value; however, a swap of pnt1 and pnt2 fails! This is the major source of confusion. In the main() method, pnt1 and pnt2 are nothing more than object references. When you pass pnt1 and pnt2 to the tricky() method, Java passes the references by value just like any other parameter. This means the references passed to the method are actually copies of the original references. Figure 1 below shows two references pointing to the same object after Java passes an object to a method.
 

Figure 1. After being passed to a method, an object will have at least two references

Java copies and passes the reference by value, not the object. Thus, method manipulation will alter the objects, since the references point to the original objects. But since the references are copies, swaps will fail. As Figure 2 illustrates, the method references swap, but not the original references. Unfortunately, after a method call, you are left with only the unswapped original references. For a swap to succeed outside of the method call, we need to swap the original references, not the copies.


Figure 2. Only the method references are swapped, not the original ones