java參数传递机制浅析
生活随笔
收集整理的這篇文章主要介紹了
java參数传递机制浅析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
歡迎轉載,轉載請聲明出處! ----------------------------------------- 前言: java語言中,參數的傳遞僅僅有一種機制。那就是值傳遞。 舉例: 以下將通過幾個樣例來說明java中的參數傳遞機制,這些樣例基本涵蓋了全部參數傳遞的情況。 1.基本數據類型: public static void testBase(int i) {i = 2;}
?測試:
int i = 10; System.out.println(i);//10 testBase(i); System.out.println(i); //10
結果當然非常顯然都是10。由于基本數據類型傳遞的是值的一份拷貝(副本),對副本操作不影響原始值。
2.對象: ? ? 2.1.對參數又一次賦值: public static void testObj(Object o) {o = new Object(); }
測試:
Object o = new Object(); System.out.println(o);// java.lang.Object@1ff61bcf testObj(o); System.out.println(o);//java.lang.Object@1ff61bcf
方法中的參數僅僅是原始對象的一份拷貝,更準確的講是地址的一份拷貝,故而對其進行又一次賦值并不會影響原始對象。
? 2.2.改變對象內部數據:
public class S {private Object o = new Object();private int i = 2;public Object getO(){return o;}public void setO(Object o){this.o = o;}public int getI(){return i;}public void setI(int i){this.i = i;} } 測試方法: public static void testA(S s) {s.setI(100);s.setO(new Object()); }
測試: S s = new S(); System.out.println(s.getI()+","+s.getO());// 2,java.lang.Object@11b75be2 testA(s); System.out.println(s.getI()+","+s.getO());//100,java.lang.Object@1cf15b84
由于對象作為參數傳遞的是對象的引用地址(注意,這是值傳遞)。故參數所指的對象和原始引用所指的對象都是堆中的同一個對象,故在測試方法中改動對象內容會改變對象的數據。
試試自己分析這個樣例(跟上面是一樣的):
package test; public class A {int t = 6;Object obj = new Object();public static void main(String[] args){A a = new A(); a.func(a.t,a.obj);//問t和obj的值是否變化。答案:不變化}public void func(int t,Object obj){t = 7;obj = null;} } 3.數組: ? ? 3.1.對參數又一次賦值: public static void testArr(int[] arr){arr = null;}測試: int[] arr = {1,2}; System.out.println(arr[0]);//1 testArr(arr); System.out.println(arr[0]); //1 傳遞機制跟對象一樣,也是傳遞的對象地址,故而也不改變原始值。 ? ???3.2.改變參數內部數據: public static void testArr(int[] arr){arr[0] = 100;}測試: int[] arr = {1,2}; System.out.println(arr[0]);//1 testArr(arr); System.out.println(arr[0]);//100 結果無須解釋了吧。 4.基本數據類型的包裝類型: ? ??事實上跟基本類型是一樣的。 public static void testWrapper(Float f) {f = 100.0f; }測試: Float f = 12.0f; System.out.println(f);//12.0 testWrapper(f); System.out.println(f);//12.0 5.【重點】字符串: 字符串作為參數的情形比較特殊。 ? ??5.1.對參數又一次賦值: public static void testStr1(String str) {str = "testOK"; }測試: String str = "test"; System.out.println(str);//testtestStr1(str);System.out.println(str);//test依據前面的思路,字符串也是對象,參數拷貝的是對象的地址。在方法內部將參數指向還有一個堆對象并不影響原始對象引用的指向。
?5.2.對參數運行替換、連接等操作: public static void testStr2(String str) {str = str.concat("OK");str = str.toUpperCase();}測試: String str = "test"; System.out.println(str);//test testStr2(str); System.out.println(str);//test
也是對str的又一次賦值。不改變原始串. ? ? 5.3.對參數運行+的操作 public static void testStr3(String str){str += "OK";}測試: String str = "test"; System.out.println(str);//test testStr3(str); System.out.println(str);//test假設你以為第二次輸出testOK。那就錯啦,String類的’+‘是經過重載的。編譯時會還原成StringBuilder的append操作,而且new了一個StringBuilder對象: str += "OK"; str = new StringBuilder(str).append("OK").toString();//編譯時會還原成這樣 顯然也是對副本又一次賦值。并不影響原始的對象。 使用javap -c反編譯一下會非常直觀:
6.StringBuffer或StringBuilder作為參數: ? ??6.1又一次賦值 public static void testStringBuilder(StringBuilder sb) {sb = new StringBuilder("testOK"); }?測試: StringBuilder sb = new StringBuilder("test"); System.out.println(sb.toString());//test testStringBuilder(sb); System.out.println(sb.toString());//test??6.2在方法內部調用StringBuffer或StringBuilder的append方法:
public static void testStringBuilder(StringBuilder sb) {sb.append("OK"); }?測試: StringBuilder sb = new StringBuilder("test"); System.out.println(sb.toString());//test testStringBuilder(sb); System.out.println(sb.toString());//testOK 7.交換問題 ? ? 經過上面的樣例。相信對java參數傳遞機制比較清楚了,所以請不要再寫這種代碼了: public static void swap(Integer a, Integer b) {Integer temp = a;a = b;b = temp; }這根本不能交換兩個數.
總結:
1.假設參數是基本數據類型(包含相應的包裝類型)。那么參數傳遞時僅僅是原始值的一份拷貝或者叫副本,對副本操作并不影響原始值; 2.假設參數是對象(引用類型),那么參數傳遞時傳遞的是對象的地址的一份拷貝,所以對對象內部屬性的操作會改變原始對象對應值,可是對該參數進行又一次賦值并不會影響原始對象; 3.String類型作為參數進行傳遞時,傳遞的也是地址。可是String類比較特殊,對參數進行concat,replace,’+‘等操作時不影響原始的串。對參數又一次賦值當然也不影響原始字符串。 4.數組類型作為參數跟傳遞對象時一樣的。
?測試:
int i = 10; System.out.println(i);//10 testBase(i); System.out.println(i); //10
結果當然非常顯然都是10。由于基本數據類型傳遞的是值的一份拷貝(副本),對副本操作不影響原始值。
2.對象: ? ? 2.1.對參數又一次賦值: public static void testObj(Object o) {o = new Object(); }
測試:
Object o = new Object(); System.out.println(o);// java.lang.Object@1ff61bcf testObj(o); System.out.println(o);//java.lang.Object@1ff61bcf
方法中的參數僅僅是原始對象的一份拷貝,更準確的講是地址的一份拷貝,故而對其進行又一次賦值并不會影響原始對象。
? 2.2.改變對象內部數據:
public class S {private Object o = new Object();private int i = 2;public Object getO(){return o;}public void setO(Object o){this.o = o;}public int getI(){return i;}public void setI(int i){this.i = i;} } 測試方法: public static void testA(S s) {s.setI(100);s.setO(new Object()); }
測試: S s = new S(); System.out.println(s.getI()+","+s.getO());// 2,java.lang.Object@11b75be2 testA(s); System.out.println(s.getI()+","+s.getO());//100,java.lang.Object@1cf15b84
由于對象作為參數傳遞的是對象的引用地址(注意,這是值傳遞)。故參數所指的對象和原始引用所指的對象都是堆中的同一個對象,故在測試方法中改動對象內容會改變對象的數據。
試試自己分析這個樣例(跟上面是一樣的):
package test; public class A {int t = 6;Object obj = new Object();public static void main(String[] args){A a = new A(); a.func(a.t,a.obj);//問t和obj的值是否變化。答案:不變化}public void func(int t,Object obj){t = 7;obj = null;} } 3.數組: ? ? 3.1.對參數又一次賦值: public static void testArr(int[] arr){arr = null;}測試: int[] arr = {1,2}; System.out.println(arr[0]);//1 testArr(arr); System.out.println(arr[0]); //1 傳遞機制跟對象一樣,也是傳遞的對象地址,故而也不改變原始值。 ? ???3.2.改變參數內部數據: public static void testArr(int[] arr){arr[0] = 100;}測試: int[] arr = {1,2}; System.out.println(arr[0]);//1 testArr(arr); System.out.println(arr[0]);//100 結果無須解釋了吧。 4.基本數據類型的包裝類型: ? ??事實上跟基本類型是一樣的。 public static void testWrapper(Float f) {f = 100.0f; }測試: Float f = 12.0f; System.out.println(f);//12.0 testWrapper(f); System.out.println(f);//12.0 5.【重點】字符串: 字符串作為參數的情形比較特殊。 ? ??5.1.對參數又一次賦值: public static void testStr1(String str) {str = "testOK"; }測試: String str = "test"; System.out.println(str);//testtestStr1(str);System.out.println(str);//test依據前面的思路,字符串也是對象,參數拷貝的是對象的地址。在方法內部將參數指向還有一個堆對象并不影響原始對象引用的指向。
?5.2.對參數運行替換、連接等操作: public static void testStr2(String str) {str = str.concat("OK");str = str.toUpperCase();}測試: String str = "test"; System.out.println(str);//test testStr2(str); System.out.println(str);//test
也是對str的又一次賦值。不改變原始串. ? ? 5.3.對參數運行+的操作 public static void testStr3(String str){str += "OK";}測試: String str = "test"; System.out.println(str);//test testStr3(str); System.out.println(str);//test假設你以為第二次輸出testOK。那就錯啦,String類的’+‘是經過重載的。編譯時會還原成StringBuilder的append操作,而且new了一個StringBuilder對象: str += "OK"; str = new StringBuilder(str).append("OK").toString();//編譯時會還原成這樣 顯然也是對副本又一次賦值。并不影響原始的對象。 使用javap -c反編譯一下會非常直觀:
6.StringBuffer或StringBuilder作為參數: ? ??6.1又一次賦值 public static void testStringBuilder(StringBuilder sb) {sb = new StringBuilder("testOK"); }?測試: StringBuilder sb = new StringBuilder("test"); System.out.println(sb.toString());//test testStringBuilder(sb); System.out.println(sb.toString());//test??6.2在方法內部調用StringBuffer或StringBuilder的append方法:
public static void testStringBuilder(StringBuilder sb) {sb.append("OK"); }?測試: StringBuilder sb = new StringBuilder("test"); System.out.println(sb.toString());//test testStringBuilder(sb); System.out.println(sb.toString());//testOK 7.交換問題 ? ? 經過上面的樣例。相信對java參數傳遞機制比較清楚了,所以請不要再寫這種代碼了: public static void swap(Integer a, Integer b) {Integer temp = a;a = b;b = temp; }這根本不能交換兩個數.
總結:
1.假設參數是基本數據類型(包含相應的包裝類型)。那么參數傳遞時僅僅是原始值的一份拷貝或者叫副本,對副本操作并不影響原始值; 2.假設參數是對象(引用類型),那么參數傳遞時傳遞的是對象的地址的一份拷貝,所以對對象內部屬性的操作會改變原始對象對應值,可是對該參數進行又一次賦值并不會影響原始對象; 3.String類型作為參數進行傳遞時,傳遞的也是地址。可是String類比較特殊,對參數進行concat,replace,’+‘等操作時不影響原始的串。對參數又一次賦值當然也不影響原始字符串。 4.數組類型作為參數跟傳遞對象時一樣的。
轉載于:https://www.cnblogs.com/mengfanrong/p/5262514.html
總結
以上是生活随笔為你收集整理的java參数传递机制浅析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java中事物的注解_编程式事务、XML
- 下一篇: 【数据结构】十字链表