關于JAVA中參數(shù)傳遞問題有兩種,,一種是按值傳遞(如果是基本類型),,另一種是按引用傳遞(如果是對象).
首先以兩個例子開始:
1) public class Test2 {
public static void main (String [] args) { StringBuffer a = new StringBuffer ("A"); StringBuffer b = new StringBuffer ("B"); operate (a,b); System.out.println(a+","+b); }
static void operate(StringBuffer x, StringBuffer y){ x.append(y); y = x; } } 輸出:AB,B
2) public class Test2 {
public static void add3 (Integer i){ int val=i.intValue(); val += 3; i = new Integer (val); }
public static void main (String args [ ] ) { Integer i = new Integer (0); add3 (i); System.out.println (i.intValue ( )); } } 輸出:0
首先我們應該明白JAVA中的參數(shù)傳遞全是以值傳遞的。是基本類型,,就拷貝一個基本類型傳進方法,;是引用,,就拷貝一個引用變量傳進去方法,理解了這兩點就能理解方法操作對象的相關問題了,。最好能畫出引用指向?qū)ο蟮膱D出來,就能完全理解了,。 第1題,,調(diào)用operate方法時,傳入了兩個引用a,b的拷貝x,y,,這兩個x,y都指向原a,b引用所指向的對象,。x.append(y)對它指向的對象(即a指向的對象)進行了操作。而x=y,,只是兩個拷貝變量在賦值,,并沒有影響到原b所指向的對象,。所以b所指向的對象仍然為B,。 第2題,i=new Integer(val)只是一個引用的拷貝指向了另外一個對象,,而原來的i仍然是指向?qū)ο髇ew Integer(0)的,。 把握住了JAVA都是傳值并且傳的都是拷貝的話,類似的題大家都能迎刃而解了,。
Java中的參數(shù)傳遞只有一種方式: by value. 理論說教太麻煩了,,直接看些例子吧: 1). 基本類型 public class A{ public static void main(String[] args){ int x = 1; System.out.println(x); //1 test(x); System.out.println(x); //還是1==>By value } static void test(int a){ a = 2; } }
2). 引用類型 public class B{ public static void main(String[] args){ Integer x = new Integer(1); System.out.println(x); test(x); System.out.println(x); } static void test(Integer a){ a = new Integer(2); } }
理解這里的關鍵是區(qū)分對象和引用。這里聲明的x是一個引用,,而不是一個對象(只是Java把它設計為看上去好像是對象一樣),。這個引用它指向了一個對象,這個對象就是后面用new關鍵字生成的對象,。因此,,可以說x指向了一個Integer對象。 在調(diào)用test方法的時候,,程序?qū)作為參數(shù)傳遞給test方法了,。這里仍然是值傳遞,在test調(diào)用過程中,,會產(chǎn)生一份新的引用(不妨叫做y),。此時,x和y指向了同一個對象,。 x和y指向的是同一個對象,,由于Java的設計,我們可以通過操作引用來達到操作對象的目的,。因此,,如果我們此時使用y來修改對象的屬性 (例如,y.someField++); 你可以看到x指向的對象同時也被修改到了,。 另一方面,,如果我們讓y指向另外一個對象,, y=new Integer(2); 此時x和y就指向了不同的 對象。y修改了它指向的對象的屬性,,很顯然不會影響到x指向的對象,。
有人說了數(shù)組。數(shù)組也是一個引用類型,,它的參數(shù)傳遞方式按照引用類型的參數(shù)傳遞一樣可以解釋得通:
import java.util.Arrays;
public class A{ public static void main(String[] args){ int[] aa = {3, 2, 1}; System.out.println(Arrays.toString(aa)); //[3, 2, 1] test(aa); System.out.println(Arrays.toString(aa)); //[3, 2, 1] test2(aa); System.out.println(Arrays.toString(aa)); //[4, 2, 1] } static void test(int[] a){ a = new int[]{1, 2, 3}; //指向了新對象 } static void test2(int[] a){ if(a != null && a.length > 0) a[0]++; //修改原來的那個對象 } }
對象是傳引用(call by reference),,簡單類型是傳值(call by value),不要被網(wǎng)上的一些概念所迷惑?。,。∧憧梢宰约鹤鰝€試驗,。 至于String等類型傳的還是引用,。如果你用concat方法,String對象的原值就會被改變,。 但你如果按如下方法: public class Test { public static void test(String str) { str = "World"; } public static void main(String[] args) { String string = "Hello"; test(string); System.out.println(string); } }
運行結(jié)果:Hello 這里str = "World" 就等同于 String str=new String("World"),。所以結(jié)果沒有改變!??!
下列程序在1處是否會有異常,如果沒有,,輸出是什么,?是否會運行到2處,如果會,,輸出是什么,?為什么會有這樣的結(jié)果?
import java.util.arraylist; import java.util.list; public class testclass {
public static void main(string args[]) { list list = new arraylist(); test2(list); system.out.println(list.size()); // 1處 test3(list); system.out.println(list.size()); // 2處 } public static void test2(list list) { list = null; } public static void test3(list list) { list.add(“aaaa“); } }
plumechen:
不會出錯的,。結(jié)果是0,,1。
因為test2(list)傳得是list的引用,,我理解成指針置的副本,,list=null;只是把那個傳入的值設置為null,,不改變原來 list的指針和內(nèi)容,。test3(list)傳入的一樣,但是執(zhí)行了list.add()由于傳入指針值的副本也指向原來的那個list的地址,,所以原來的那個list的內(nèi)容就改變了,,size變成了1了
6.下列正確的有()
A. call by value不會改變實際參數(shù)的數(shù)值
B. call by reference能改變實際參數(shù)的參考地址
C. call by reference不能改變實際參數(shù)的參考地址
D. call by reference能改變實際參數(shù)的內(nèi)容
答案:ACD
Java中的參數(shù)傳遞只有一種方式: 值傳遞 (by value)
1、簡單類型類型,,在調(diào)用的方法中,,直接是實參的一個拷貝
2,、對象:程序?qū)ο髕作為參數(shù)傳遞給方法了。這里仍然是值傳遞,,在方法調(diào)用過程中,,會產(chǎn)生一份新的引用(不妨叫做y)。此時,,x和y指向了同一個對象,。
我們可以通過操作引用來達到操作對象的目的。因此,,如果我們此時使用y來修改對象的屬性 (例如,,y.someField++); 你可以看到x指向的對象同時也被修改到了。(值傳遞,,在方法里產(chǎn)生引用,,操作引用達到操作對象。所以引用可以修改實參(對象)的內(nèi)容)
實驗
package callbyvalue;
//public class Test2 { // // public static void main (String [] args) { // StringBuffer a = new StringBuffer ("A"); // StringBuffer b = new StringBuffer ("B"); // operate (a,b); // System.out.println(a+","+b); //AB,B // } // // static void operate(StringBuffer x, StringBuffer y){ //JAVA中的參數(shù)傳遞全是以值傳遞的,。 // //是基本類型,,就拷貝一個基本類型傳進方法;是引用,,就拷貝一個引用變量傳進去方法 // x.append(y); //x.append(y)對它指向的對象(即a指向的對象)進行了操作 // y = x; //只是兩個拷貝變量在賦值 并不會影響原來的對象 // System.out.println(y); //AB // } // }
//public class Test2 { // // public static void add3 (Integer i){ // int val=i.intValue(); // val += 3; // i = new Integer (val); //只是一個引用的拷貝指向了另外一個對象,而原來的i仍然是指向?qū)ο髇ew Integer(0)的 // } // // public static void main (String args [ ] ) { // Integer i = new Integer (0); // add3 (i); // System.out.println (i.intValue ( )); //0 // } // }
//public class Test2 { //我的實驗 // // public static void change (int i){ // i=6; //給拷貝賦值,,并沒有改變a指向的值 // } // // public static void main (String args [ ] ) { // int a=5; // change(a); // System.out.println (a); //5 JAVA都是傳值并且傳的都是拷貝的話 // } // }
//public class Test2 { //我的實驗 // // public static void change (int i){ // i++; //對象是傳引用(call by reference),,簡單類型是傳值(call by value) // //傳值(call by value)不會改變實際參數(shù)的數(shù)值 // } // // public static void main (String args [ ] ) { // int a=5; // change(a); // System.out.println (a); //5 // } // }
|