java int 传引用吗_Java的参数传递是「值传递」还是「引用传递」?
關于Java傳參時是引用傳遞還是值傳遞,一直是一個討論比較多的話題。
有人說Java中只有值傳遞,也有人說值傳遞和引用傳遞都是存在的,比較容易讓人產生疑問。
關于值傳遞和引用傳遞其實需要分情況看待。
一、Java數據類型
我們都知道,Java數據類型分為「基本數據類型」和「引用類型」兩大類。
基本數據類型(8種)
引用類型(3種)
引用類型可分為類引用類型(類)、接口引用類型(接口)和數組引用類型(數組)。以下代碼定義了3個引用變量:user、myThread、intArray:
User user;
java.lang.Runnable myThread;int[] intArray;
其中user變量位類引用類型,myThread變量為接口引用類型,而intArray變量為數組引用類型。myThread變量之所以是接口引用類型,是因為java.lang.Runnable是接口,而不是類。
類引用類型的變量引用這個類或者其子類的實例,接口引用類型的變量引用實現了這個接口的類的實例,數組引用類型的變量引用引用這個數組類型的實例。在Java語言中,數組也被看作對象。由此可見,不管是何種引用類型的變量,他們引用的都是對象。
如果一個引用類型變量不引用任何對象,那么可以把它賦值為null。在初始化一個引用類型變量時,常常給它賦初值為null。
User user = null;
方法的參數分為實際參數和形式參數。
實際參數:調用方法時寫的具體數值。
形式參數:定義方法時寫的參數。
一般情況下,在數據做為參數傳遞的時候,基本數據類型是值傳遞,引用數據類型是引用傳遞(地址傳遞)。
值傳遞
public static voidmain(String[] args) {int num1 = 100;int num2 = 200;
take(num1, num2);
System.out.println("num1 = " +num1);
System.out.println("num2 = " +num2);
}public static void take(int a, intb) {int temp =a;
a=b;
b=temp;
System.out.println("a = " +a);
System.out.println("b = " +b);
}
運行結果:
a = 200b= 100num1= 100num2= 200
流程
主函數進棧,num1、num2初始化。
調用take方法,take()進棧,將num1和num2的值復制一份給a和b。
take方法中對a和b的值進行交換。
take方法運行完畢,a、b的值已經交換。
take方法彈棧。
主函數彈棧。
解析
在take方法中,a、b的值進行交換,并不會影響到num1和num2。因為a、b中的值只是從num1、num2中復制過來的。也就是說a、b相當于num1、num2的副本,副本的內容無論怎么修改,都不會影響到原件本身。
引用傳遞
public static voidmain(String[] args) {int[] intArray = {1,2,3,4,5};
change(intArray);
System.out.println(intArray[0]);
}public static void change(int[] array) {int len =array.length;
array[0] = 0;
}
運行結果:
0
流程
主函數進棧,int[] intArray初始化。
調用change方法,change()進棧,將intArray的地址值,復制一份給array。
change方法中,根據地址值,找到堆中的數組,并將第一個元素的值改為0。
change方法運行完畢,數組中第一個元素的值已經改變。
change方法彈棧。
主函數彈棧。
解析
調用change()的時候,形參array接收的是intArray地址值的副本。并在change方法中,通過地址值,對數組進行操作。change方法彈棧以后,數組中的值已經改變。main方法中,打印出來的intArray[0]也就從原來的1變成了0。
無論是主函數,還是change方法,操作的都是同一個地址值對應的數組。
就像你把自己家的鑰匙給了一把給保姆,保姆拿到鑰匙在你家打掃衛生,結束后走了。等你拿著鑰匙回到家以后,家里已經煥然一新。這里的鑰匙就相當于地址值,家就相當于數組本身。
String類型傳遞
public static voidmain(String[] args) {
String str= "ABC";
change(str);
System.out.println(str);
}public static voidchange(String a) {
a= "DEF";
}
運行結果:
ABC
這就奇怪了。String是一個類,類是類引用類型,作為參數傳遞的時候,應該是引用傳遞。但是從結果看起來卻是值傳遞。
原因
String的Api文檔中有這么一句話:
意思是String的值在創建之后不能被改變。
Api中還有一段:
意思是
String str = "abc";
相當于:char data[] = {'a', 'b', 'c'};
String str= new String(data);
也就是說對String類型的str的任何修改相當于重新創建一個對象,并將新的地址值賦給str。這樣的話,上面的代碼就可以寫成這樣:
public static voidmain(String[] args) {
String str1= "ABC";
change(str1);
System.out.println(str1);
}public static voidchange(String a) {char data[] = {'D', 'E', 'F'};
String str= newString(data);
a=str;
}
流程
主函數進棧,str1初始化。
調用change方法,change()進棧,將str1的地址值復制一份給a。
change方法中,重新創建一個String對象"DEF",并將a指向了新的地址值。
change方法執行完畢,a指向的地址值已經發生改變。
change方法彈棧。
主函數彈棧。
解析
String對象作為參數傳遞時,走的依然是引用傳遞,只不過String這個類比較特殊。String對象一旦創建,內容便不可更改,每一次內容的更改都是重新創建出來的新對象。當change方法執行完畢時,a所指向的地址值已經發生改變,而a本來的地址值就是復制過來的副本,所以并不能改變str1的值。
String類型類似情況
classUser {
String name;publicUser(String name) {this.name =name;
}
}public static voidmain(String[] args) {
User user= new User("張三");
change(user);
System.out.println(user.name);
}public static voidchange(User u) {
User user= new User("李四");
u=user;
}
運行結果:
張三
總結
Java基本數據類型傳遞參數時是值傳遞;引用類型傳遞參數時是引用傳遞。
值傳遞時,將實參的值傳遞一份給形參;引用傳遞時,將實參的地址值傳遞一份給形參。
值傳遞時,實參把它的值傳遞給對應的形參,函數接收的是原始值的一個拷貝,此時內存中存在兩個相等的基本類型,即實參和形參,后面方法中的操作都是對形參這個值的修改,不影響實參的值。引用傳遞時,實參的引用(地址,而不是參數的值)被傳遞給方法中相對應的形參,函數接收的是原始值的內存地址;在方法執行中,形參和實參內容相同,指向同一塊內存地址,方法執行中對引用的操作將會影響到實際對象。
需要特殊考慮String,以及Integer、Double等幾個基本類型包裝類,它們都是immutable類型,因為沒有提供自身修改的函數,每次操作都是新創建一個對象,所以要特殊對待。因為最后的操作不會修改實參,可以認為是和基本數據類型相似,為值傳遞。
總結
以上是生活随笔為你收集整理的java int 传引用吗_Java的参数传递是「值传递」还是「引用传递」?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux书(学习linux的书)
- 下一篇: java 消息队列服务_ActiveMQ