Java支持兩種數(shù)據(jù)類型:基本數(shù)據(jù)類型和引用數(shù)據(jù)類型。
原始數(shù)據(jù)類型是一個(gè)簡單的數(shù)據(jù)結(jié)構(gòu),它只有一個(gè)與之相關(guān)的值。 引用數(shù)據(jù)類型是一個(gè)復(fù)雜的數(shù)據(jù)結(jié)構(gòu),它表示一個(gè)對象。
原始數(shù)據(jù)類型的變量將該值直接存儲(chǔ)在其存儲(chǔ)器地址處。使用對象和引用變量時(shí)會(huì)有所不同。Java中的所有參數(shù)都通過值傳遞。
當(dāng)參數(shù)是原始數(shù)據(jù)類型時(shí),實(shí)際參數(shù)的值將復(fù)制到參數(shù)。
在方法主體中對參數(shù)值進(jìn)行的任何更改只會(huì)更改形式參數(shù)的副本,而不會(huì)更改實(shí)際參數(shù)的值。當(dāng)參數(shù)通過參考值傳遞時(shí),存儲(chǔ)在實(shí)際參數(shù)中的參考被復(fù)制到形式參數(shù)。 實(shí)際參數(shù)和形式參數(shù)都指向內(nèi)存中的相同對象。
可以將另一個(gè)對象的引用分配給方法主體中的形式參數(shù)。
下面的代碼演示了Java中的引用傳遞機(jī)制。
class Phone {
public String model = "Unknown";
public int year = 2016;
public double price = 0.0;
}
public class Main {
public static void main(String[] args) {
Phone myPhone = new Phone();
myPhone.model = "iPhone";
myPhone.year = 2018;
myPhone.price = 16000.0;
System.out.println("#1: model = " + myPhone.model + ", year = "
+ myPhone.year + ", price = " + myPhone.price);
Main.test(myPhone);
System.out.println("#4: model = " + myPhone.model + ", year = "
+ myPhone.year + ", price = " + myPhone.price);
}
public static void test(Phone xPhone) {
System.out.println("#2: model = " + xPhone.model + ", year = "
+ xPhone.year + ", price = " + xPhone.price);
// Let's make xyCar refer to a new object
xPhone = new Phone();
System.out.println("#3: model = " + xPhone.model + ", year = "
+ xPhone.year + ", price = " + xPhone.price);
}
}
上面的代碼生成以下結(jié)果。
#1: model = iPhone, year = 2018, price = 16000.0
#2: model = iPhone, year = 2018, price = 16000.0
#3: model = Unknown, year = 2016, price = 0.0
#4: model = iPhone, year = 2018, price = 16000.0
注意
當(dāng)引用類型參數(shù)傳遞給方法時(shí),形式參數(shù)可以訪問對象,實(shí)際參數(shù)也可以訪問該對象。
形式參數(shù)可以通過直接更改實(shí)例變量的值或通過調(diào)用對象上的方法來修改對象。通過形式參數(shù)對對象進(jìn)行的任何修改都可以通過實(shí)際參數(shù)立即可見,因?yàn)樗鼈兌急4鎸?nèi)存中同一對象的引用。形式參數(shù)本身可以被修改以引用方法內(nèi)的另一個(gè)對象。
要禁用將引用類型形式參數(shù)更改為引用不同對象的方法,請?jiān)谝妙愋托问絽?shù)聲明中使用關(guān)鍵字final
。
public class Main {
public static void main(String[] args) {
Phone myPhone = new Phone();
myPhone.model = "iPhone";
myPhone.year = 2017;
myPhone.price = 16000.0;
Main.test(myPhone);
}
public static void test(final Phone xPhone) {
System.out.println("#2: model = " + xPhone.model + ", year = "
+ xPhone.year + ", price = " + xPhone.price);
// Let's make xyCar refer to a new object
//xPhone = new Phone();
}
}
class Phone {
public String model = "Unknown";
public int year = 2014;
public double price = 0.0;
}
上面的代碼生成以下結(jié)果。
#2: model = iPhone, year = 2017, price = 16000.0