參數是按值而不是按引用傳遞的說明 Java 應用程序有且僅有的一種參數傳遞機制,即按值傳遞。
在 Java 應用程序中永遠不會傳遞對象,而只傳遞對象引用。因此是按引用傳遞對象。Java 應用程序按引用傳遞對象這一事實並不意味着 Java 應用程序按引用傳遞參數。參數可以是對象引用,而 Java 應用程序是按值傳遞對象引用的。
Java 應用程序中的變量可以為以下兩種類型之一:引用類型或基本類型。當作為參數傳遞給一個方法時,處理這兩種類型的方式是相同的。兩種類型都是按值傳遞的;沒有一種按引用傳遞。
按值傳遞和按引用傳遞。按值傳遞意味着當將一個參數傳遞給一個函數時,函數接收的是原始值的一個副本。因此,如果函數修改了該參數,僅改變副本,而原始值保持不變。按引用傳遞意味着當將一個參數傳遞給一個函數時,函數接收的是原始值的內存地址,而不是值的副本。因此,如果函數修改了該參數,調用代碼中的原始值也隨之改變。
1、對象是按引用傳遞的
2、Java 應用程序有且僅有的一種參數傳遞機制,即按值傳遞
3、按值傳遞意味着當將一個參數傳遞給一個函數時,函數接收的是原始值的一個副本
4、按引用傳遞意味着當將一個參數傳遞給一個函數時,函數接收的是原始值的內存地址,而不是值的副本
首先考試大來看看第一點:對象是按引用傳遞的
確實,這一點我想大家沒有任何疑問,例如:
class Test01
{
public static void main(String[] args)
{
StringBuffer s= new StringBuffer("good");
StringBuffer s2=s;
s2.append(" afternoon.");
System.out.println(s);
}
}
對象s和s2指向的是內存中的同一個地址因此指向的也是同一個對象。
如何解釋“對象是按引用傳遞的”的呢?
這里的意思是進行對象賦值操作是傳遞的是對象的引用,因此對象是按引用傳遞的,有問題嗎?
程序運行的輸出是:
good afternoon.
這說明s2和s是同一個對象。
這里有一點要澄清的是,這里的傳對象其實也是傳值,因為對象就是一個指針,這個賦值是指針之間的賦值,因此在java中就將它說成了傳引用。(引用是什么?不就是地址嗎?地址是什么,不過就是一個整數值)
再看看下面的例子:
class Test02
{
public static void main(String[] args)
{
int i=5;
int i2=i;
i2=6;
System.out.println(i);
}
}
程序的結果是什么?5!!!
這說明什么,原始數據類型是按值傳遞的,這個按值傳遞也是指的是進行賦值時的行為下一個問題:Java 應用程序有且僅有的一種參數傳遞機制,即按值傳遞
class Test03
{
public static void main(String[] args)
{
StringBuffer s= new StringBuffer("good");
StringBuffer s2=new StringBuffer("bad");
test(s,s2);
System.out.println(s);//9
System.out.println(s2);//10
}
static void test(StringBuffer s,StringBuffer s2) {
System.out.println(s);//1
System.out.println(s2);//2
s2=s;//3
s=new StringBuffer("new");//4
System.out.println(s);//5
System.out.println(s2);//6
s.append("hah");//7
s2.append("hah");//8
}
}
程序的輸出是:
good
bad
new
good
goodhah
bad
考試大提示: 為什么輸出是這樣的?
這里需要強調的是“參數傳遞機制”,它是與賦值語句時的傳遞機制的不同。
我們看到1,2處的輸出與我們的預計是完全匹配的
3將s2指向s,4將s指向一個新的對象
因此5的輸出打印的是新創建的對象的內容,而6打印的原來的s的內容
7和8兩個地方修改對象內容,但是9和10的輸出為什么是那樣的呢?
Java 應用程序有且僅有的一種參數傳遞機制,即按值傳遞。
至此,我想總結一下我對這個問題的最后的看法和我認為可以幫助大家理解的一種方法:
我們可以將java中的對象理解為c/c++中的指針
例如在c/c++中:
int *p;
print(p);//1
*p=5;
print(*p);//2
1打印的結果是什么,一個16進制的地址,2打印的結果是什么?5,也就是指針指向的內容。
即使在c/c++中,這個指針其實也是一個32位的整數,我們可以理解我一個long型的值。
而在java中一個對象s是什么,同樣也是一個指針,也是一個int型的整數(對於JVM而言),我們在直接使用(即s2=s這樣的情況,但是對於System.out.print(s)這種情況例外,因為它實際上被晃猄ystem.out.print(s.toString()))對象時它是一個int的整數,這個可以同時解釋賦值的傳引用和傳參數時的傳值(在這兩種情況下都是直接使用),而我們在s.XXX這樣的情況下時s其實就是c/c++中的*s這樣的使用了。這種在不同的使用情況下出現不同的結果是java為我們做的一種簡化,但是對於c/c++程序員可能是一種誤導。java中有很多中這種根據上下文進行自動識別和處理的情況,下面是一個有點極端的情況:
class t
{
public static String t="t";
public static void main(String[] args)
{
t t =new t();
t.t();
}
static void t() {
System.out.println(t);
}
}
1.對象就是傳引用
2.原始類型就是傳值
3.String類型因為沒有提供自身修改的函數,每次操作都是新生成一個String對象,所以要特殊對待。可以認為是傳值。