引言
最近刷牛客網上的題目時碰到不少有關Java按值傳遞和按引用傳遞的問題,這種題目就是坑呀,在做錯了n次之后,查找了多方資料進行總結既可以讓自己在總結中得到提高,又可以讓其他人少走彎路。何樂而不為?
Java按值傳遞和按引用傳遞
首先問一句:Is Java “pass-by-reference” or “pass-by-value”? Java到底是按值傳遞還是按引用傳遞的呢?國外的網站上關於這個問題的討論非常之多。官方答案:The Java Spec says that everything in Java is pass-by-value. There is no such thing as “pass-by-reference” in Java. 官方的說法是在java中只有按值傳遞,並沒有所謂的按引用傳遞。
基本數據類型的按值傳遞
java數據類型可以分為兩大類:基本類型(primitive types)和引用類型(reference types)。primitive types 包括boolean類型以及數值類型(numeric types)。numeric types又分為整型(integer types)和浮點型(floating-point type)。整型有5種:byte short int long char(char本質上是一種特殊的int)。浮點類型有float和double。關系整理一下如下圖:
public class Swap { public static void main(String[] args) { int x = 10; int y = 20; swap(x, y); System.out.println("x(2) = " + x); System.out.println("y(2) = " + y); } public static void swap(int x, int y) { int temp = x; x = y; y = temp; System.out.println("x(1) = " + x); System.out.println("y(1) = " + y); } } /*輸出 x(1) = 20 y(1) = 10 x(2) = 10 y(2) = 20 */
上面程序main函數調用swap函數來交換 x,y的值,然而調用函數之后發現main中x,y的值並未交換。包括在Java api中找不到一個可以交換兩個變量的方法。這與Java語言的特性有關。通過一個圖就可以知道上面程序的運行結果了。
由上圖可知,main函數中的x,y和swap函數中的x,y分別存放在不同的區域,在main中調用swap函數的時候,會將main中的x,y的值賦給swap中的x,y。當swap函數中對x,y交換時只是對swap幀中的x,y做交換,並不會改變main中的x,y。所以當函數返回時main中的x,y並不會改變。swap執行過程圖如下:
對於基本數據類型 short int long float double char byte boolean這八種按值傳遞調用函數並不會改變在原函數中的值。
引用數據類型的按值傳遞
引用數據數據類型分為三種:①接口 ②類 ③數組對於引用數據類型的按值傳遞先給出一個實例對比實例進行分析。
例2
public static void main(String[] args) { int []a={10,20}; System.out.println("a[0] :"a[0]+"a[1] : "+a[1]);//a[0]=10,a[1]=20; swap(a, 0, 1); System.out.println("a[0] :"a[0]+"a[1] : "+a[1]);//a[0]=20,a[1]=10; } public static void swap(int []a,int i,int j){ int temp=a[i]; a[i]=a[j]; a[j]=temp; System.out.println("a[0] :"a[0]+"a[1] : "+a[1]);//a[0]=20,a[1]=10; } //輸出 /*a[0]=10 a[1]=20 a[0]=20 a[1]=10 a[0]=20 a[1]=10 */
運行程序后發現,swap函數對a[0] ,a[1]的操作竟然影響到了main函數中的a[0] ,a[1]的值,真是不可思議。為什么會產生如此之結果。原來引用類型的按值傳遞,傳遞的是對象的地址。還是用圖來解釋一下。
這里寫圖片描述
由圖可以看出在swap中僅僅是得到了數組的地址,並沒有對數組的元素進行復制,在swap中對數組的操作是直接對main函數中數組的操作,因此swap函數返回后main函數中的a[0] ,a[1]的值發生交換。
數組、類、接口按值傳遞的時候都是傳遞對象的地址。再來看一個比較復雜的實例。
public class Main{ public static void main(String[] args){ Foo f = new Foo("f"); changeReference(f); // It won't change the reference! modifyReference(f); // It will modify the object that the reference variable "f" refers to! } public static void changeReference(Foo a){ Foo b = new Foo("b"); a = b; } public static void modifyReference(Foo c){ c.setAttribute("c"); } }
經典筆試題 :
public class Demo { public static void main(String[] args) { //demo1 String str=new String("hello"); char []chs={'w','o','r','l','d'}; change(str, chs); System.out.println(str+" "+new String(chs)); //------------------------------------------------- //demo2 StringBuffer sb=new StringBuffer("hello"); change(sb); System.out.println(sb); } public static void change(StringBuffer sb) { sb.append(" world"); // sb.deleteCharAt(0); } public static void change(String str,char[]chs) { str.replace('h', 'H'); chs[0]='W'; } }
上面程序段demo1和demo2分別輸出什么,這里涉及到String特性,這道題目會做了,Java按值傳遞和按引用傳遞就徹底懂了,答案和解析先匿了。
答案 : hello World
hello world
原文
https://blog.csdn.net/u013309870/article/details/75499175