java 中是引用傳遞還是值傳遞,讓我們來一探究竟! —— 由 Cool 分享
在學習Java編程語言過程中最容易讓你產生誤解的問題之一就是 java是值傳遞還是引用傳遞。今天就來圍繞這個話題揭開迷霧。
首先先來認識一下什么是值傳遞什么是引用傳遞。
值傳遞: 將方法實際參數值復制到另一個變量,然后復制的對象被傳遞,這就是為什么它被稱為“值傳遞”
引用傳遞:將實際參數的引用傳遞給該方法,這就是為什么它被引用稱為“傳遞”的原因。
問題:如果java是使用引用傳遞的話,為什么在函數中 變量的交換會沒有卵用呢?答案:java通過引用來操作對象,并且所有Object類型的變量都是引用一個地址。但是,java傳遞方法參數并不是引用傳遞,而是值傳遞。來個例子,大家感受一下:
public void badSwap(int var1, int var2){ int temp = var1; var1 = var2; var2 = temp;}當badSwap()方法結束,原先作為實際參數傳遞進來的變量仍然是它們原來的值,也就是這個方法然無卵用。如果把這個方法的參數由int改變成Object類,結果依然一樣。因為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)}構造了兩個對象pnt1和pnt2,并且初始的x,y值都是0。之后傳入tricky()方 法,在方法中修改行參args1的x,y的值,之后交換行參的指向。
執行main方法 ,輸入如下
X: 0 Y: 0X: 0 Y: 0X: 100 Y: 100X: 0 Y: 0根據輸出結果,可以發現實際參數pnt1的值被修改了,pnt2的屬性沒有變,也就是pnt1盒pnt2的交換失敗了!這里最容易被疑惑。 pnt1和pnt2肯定是對象引用,當把pnt1和pnt2傳入到tricky()方法當中, 由于java是值傳遞,也就類似于復制,相當于復制和一個和pnt1一樣的行參變量arg1,它也擁有了一個和pnt1變量同一指向的引用。圖一展示了通過值傳遞之后兩個引用指向同一個地址。
圖1。方法中被傳入對象引用參數之后,一個對象至少會有兩個引用
上面的例子由于兩個變量的引用都指向了同一個對象,所以在方法中修改對象的值會生效。但是由于arg1是copy的一個變量,所以交換的話只是交換了arg1的指向,這就是為什么交換會失敗的原因。
圖2展示了僅僅是方法參數里的引用交換了,而并不是原始的參數交換。
如果需要成功交換pnt1和pnt2的引用,只能在外部直接修改他們的引用即可。
圖2:java通過值傳遞,copy了一個和pnt1一樣的變量,他們擁有同樣的引用。在方法調用之后,僅僅是交換了arg1和arg2的引用。
在國內可能有大部分的人清楚傳遞的規律,但是他們依然習慣是基本類型是值傳遞,引用類型變量就是引用傳遞,因為方法中的參數的確有了外部變量的引用。這個看個人理解。我更偏向于是值傳遞:通過值傳遞之后方法里的參數擁有了和實際參數一樣的值(基礎類型為值,對象類型為引用),所以才擁有了引用。而如果是引用傳遞的話,那就是是直接傳遞一個存放于堆區的對象給(也就是直是復制了一個對象)。當然這只是我個人的認識。
例子分析2
public class Test { private static int a; private int b; public static void main(String[] args) { System.out.println(a); modify(a); System.out.println(a); return; } private static void modify(int a) { a++; }}知道了java是值傳遞的,結果很清楚了
輸出a的值肯定不變。
java總是通過值傳遞而不是引用傳遞,再來一個例子
例子分析3
public class Balloon { private String color; public Balloon(){} public Balloon(String c){ this.color=c; } public String getColor() { return color; } public void setColor(String color) { this.color = color; }}Balloon類擁有一個color屬性。
public class Test { public static void main(String[] args) { Balloon red = new Balloon("Red"); Balloon blue = new Balloon("Blue"); swap(red, blue); System.out.println("red color="+red.getColor()); System.out.println("blue color="+blue.getColor()); foo(blue); System.out.println("blue color="+blue.getColor()); } private static void foo(Balloon balloon) { balloon.setColor("Red"); balloon = new Balloon("Green"); balloon.setColor("Blue"); } public static void swap(Object o1, Object o2){ Object temp = o1; o1=o2; o2=temp; }}答案:red blue red
新聞熱點
疑難解答