1. 簡單類型是按值傳遞的
Java 方法的參數(shù)是簡單類型的時候,是按值傳遞的 (pass by value)。這一點我們可以通過一個簡單的例子來說明:
/* 例 1 */
/**
* @(#) Test.java
* @author fancy
*/
public class Test {
public static void test(boolean test) {
test = ! test;
System.out.println("In test(boolean) : test = " + test);
}
public static void main(String[] args) {
boolean test = true;
System.out.println("Before test(boolean) : test = " + test);
test(test);
System.out.println("After test(boolean) : test = " + test);
}
}
運行結果:
Before test(boolean) : test = true
In test(boolean) : test = false
After test(boolean) : test = true
不難看出,雖然在 test(boolean) 方法中改變了傳進來的參數(shù)的值,但對這個參數(shù)源變量本身并沒有影響,即對 main(String[]) 方法里的 test 變量沒有影響。那說明,參數(shù)類型是簡單類型的時候,是按值傳遞的。以參數(shù)形式傳遞簡單類型的變量時,實際上是將參數(shù)的值作了一個拷貝傳進方法函數(shù)的,那么在方法函數(shù)里再怎么改變其值,其結果都是只改變了拷貝的值,而不是源值。
簡單的說,引用其實就像是一個對象的名字或者別名 (alias),一個對象在內(nèi)存中會請求一塊空間來保存數(shù)據(jù),根據(jù)對象的大小,它可能需要占用的空間大小也不等。訪問對象的時候,我們不會直接是訪問對象在內(nèi)存中的數(shù)據(jù),而是通過引用去訪問。引用也是一種數(shù)據(jù)類型,我們可以把它想象為類似 C 語言中指針的東西,它指示了對象在內(nèi)存中的地址——只不過我們不能夠觀察到這個地址究竟是什么。
C 語言中有一種數(shù)據(jù)類型叫做指針,于是將一個數(shù)據(jù)作為參數(shù)傳遞給某個函數(shù)的時候,就有兩種方式:傳值,或是傳指針,它們的區(qū)別,可以用一個簡單的例子說明:
/* 例 5 */
/**
* @(#) test.c
* @author fancy
*/
void SwapValue(int a, int b) {
int t = a;
a = b;
b = t;
}
void SwapPointer(int * a, int * b) {
int t = * a;
* a = * b;
* b = t;
}
void main() {
int a = 0, b = 1;
printf("1 : a = %d, b = %d\n", a, b);
SwapValue(a, b);
printf("2 : a = %d, b = %d\n", a, b);
SwapPointer(&a, &b);
printf("3 : a = %d, b = %d\n", a, b);
}
運行結果:
1 : a = 0, b = 1
2 : a = 0, b = 1
3 : a = 1, b = 0
大家可以明顯的看到,按指針傳遞參數(shù)可以方便的修改通過參數(shù)傳遞進來的值,而按值傳遞就不行。
當 Java 成長起來的時候,許多的 C 程序員開始轉(zhuǎn)向?qū)W習 Java,他們發(fā)現(xiàn),使用類似 SwapValue 的方法仍然不能改變通過參數(shù)傳遞進來的簡單數(shù)據(jù)類型的值,但是如果是一個對象,則可能將其成員隨意更改。于是他們覺得這很像是 C 語言中傳值/傳指針的問題。但是 Java 中沒有指針,那么這個問題就演變成了傳值/傳引用的問題?上⑦@個問題放在 Java 中進行討論并不恰當。
/** 例 6 */
/**
* @(#) Test.java
* @author fancy
*/
public class Test {
public static void swap(int[] data, int a, int b) {
int t = data[a];
data[a] = data;
data = t;
}
public static void main(String[] args) {
int[] data = new int[10];
for (int i = 0; i < 10; i++) {
data = (int) (Math.random() * 100);
System.out.print(" " + data);
}
System.out.println();
for (int i = 0; i < 9; i++) {
for (int j = i; j < 10; j++) {
if (data >; data[j]) {
swap(data, i, j);
}
}
}
for (int i = 0; i < 10; i++) {
System.out.print(" " + data);
}
System.out.println();
}
}
運行結果(情況之一):
78 69 94 38 95 31 50 97 84 1
1 31 38 50 69 78 84 94 95 97
swap(int[] data, int a, int b) 方法在內(nèi)部實際上是改變了 data 所指示的對象的成員數(shù)據(jù),即上述討論的第二種改變參數(shù)值的方法。希望大家能夠舉一反三,使用類似的方法來解決相關問題。