Java中的值傳遞和引用傳遞

Java中沒有指針,所以也沒有引用傳遞了,僅僅有值傳遞不過可以通過對象的方式來實現引用傳遞,類似java沒有多繼承但可以用多次implements 實現多繼承的功能。

值傳遞:方法調用時,實際參數把它的值傳遞給對應的形式參數,方法執行中形式參數值的改變不影響實際參 數的值。

引用傳遞:也稱為傳地址。方法調用時,實際參數的引用(地址,而不是參數的值)被傳遞給方法中相對應的形式參數,在方法執行中,對形式參數的操作實際上就是對實際參數的操作,方法執行中形式參數值的改變將會影響實際參數的值。

Java參數按值傳遞

 

面試題:當一個對象被當作參數傳遞到一個方法后,此方法可改變這個對象的屬性,并可返回變化后的結果,那么這里到底是值傳遞還是引用傳遞?

    :是值傳遞。Java 只有值傳遞參數。當一個對象實例作為一個參數被傳遞到方法中時,參數的值就是該對象的引用一個副本。指向同一個對象,對象的內容可以在被調用的方法中改變,但對象的引用(不是引用的副本)是永遠不會改變的。

 

-------------------------------------------------------------

 

Java 應用程序中永遠不會傳遞對象,而只傳遞對象引用。因此是按引用傳遞對象。但重要的是要區分參數是如何傳遞的,這才是該節選的意圖。Java 應用程序按引用傳遞對象這一事實并不意味著 Java 應用程序按引用傳遞參數。參數可以是對象引用,而 Java 應用程序是按值傳遞對象引用的。

 

Java 應用程序中的變量可以為以下兩種類型之一:引用類型或基本類型。當作為參數傳遞給一個方法時,處理這兩種類型的方式是相同的。兩種類型都是按值傳遞的;沒有一種按引用傳遞。

  

按值傳遞意味著當將一個參數傳遞給一個函數時,函數接收的是原始值的一個副本。因此,如果函數修改了該參數,僅改變副本,而原始值保持不變。按引用傳遞意味著當將一個參數傳遞給一個函數時,函數接收的是原始值的地址,而不是值的副本。因此,如果函數修改了該參數的值,調用代碼中的原始值也隨之改變。如果函數修改了該參數的地址,調用代碼中的原始值不會改變.

  

當傳遞給函數的參數不是引用時,傳遞的都是該值的一個副本(按值傳遞)。區別在于引用。在 C++ 中當傳遞給函數的參數是引用時,您傳遞的就是這個引用,或者內存地址(按引用傳遞)。在 Java 應用程序中,當對象引用是傳遞給方法的一個參數時,您傳遞的是該引用的一個副本(按值傳遞),而不是引用本身。

  

Java 應用程序按值傳遞參數(引用類型或基本類型),其實都是傳遞的一份拷貝.而不是數據本身.(不是像 C++ 中那樣對原始值進行操作。)

 

 

Java代碼  收藏代碼

 

    1:  

    Java代碼 復制代碼  

      

       1. //在函數中傳遞基本數據類型,     

       2. public class Test {     

       3.               

       4.     public static void change(int i, int j) {     

       5.         int temp = i;     

       6.         i = j;     

       7.         j = temp;     

       8.     }     

       9.     

      10.     public static void main(String[] args) {     

      11.         int a = 3;     

      12.         int b = 4;     

      13.         change(a, b);     

      14.     

      15.         System.out.println("a=" + a);     

      16.         System.out.println("b=" + b);     

      17.     }     

      18. }     

      19.     

      20. 結果為:     

      21. a=3    

      22. b=4    

      23. 原因就是 參數中傳遞的是 基本類型 a b 的拷貝,在函數中交換的也是那份拷貝的值 而不是數據本身;    

 

 

 

 

 

Java代碼  收藏代碼

 

    2:  

    Java代碼 復制代碼  

      

       1. //傳的是引用數據類型     

       2. public class Test {     

       3.     

       4.     public static void change(int[] counts) {     

       5.         counts[0] = 6;     

       6.         System.out.println(counts[0]);     

       7.     }     

       8.     

       9.     public static void main(String[] args) {     

      10.         int[] count = { 1, 2, 3, 4, 5 };     

      11.         change(count);     

      12.     }     

      13. }     

      14.     

      15. 在方法中 傳遞引用數據類型int數組,實際上傳遞的是其引用count的拷貝,他們都指向數組對象,在方法中可以改變數組對象的內容。即:對復制的引用所調用的方法更改的是同一個對象。   

 

 

 

 

 

Java代碼  收藏代碼

 

    3:  

    Java代碼 復制代碼  

      

       1. //對象的引用(不是引用的副本)是永遠不會改變的     

       2. class A {     

       3.     int i = 0;     

       4. }     

       5.     

       6.     

       7. public class Test {     

       8.     

       9.     public static void add(A a) {     

      10.         a = new A();     

      11.         a.i++;     

      12.     }     

      13.          

      14.     public static void main(String args[]) {     

      15.         A a = new A();     

      16.         add(a);     

      17.         System.out.println(a.i);     

      18.     }     

      19. }     

      20.     

      21. 輸出結果是0    

      22. 在該程序中,對象的引用指向的是A ,而在change方法中,傳遞的引用的一份副本則指向了一個新的OBJECT,并對其進行操作。     

      23. 而原來的A對象并沒有發生任何變化。 引用指向的是還是原來的A對象。   

 

 

 

 

 

 

Java代碼  收藏代碼

 

    4:  

    String 不改變,數組改變  

    Java代碼 復制代碼  

      

       1.     

       2. public class Example {     

       3.     String str = new String("good");     

       4.     

       5.     char[] ch = { 'a', 'b', 'c' };     

       6.     

       7.     public static void main(String args[]) {     

       8.         Example ex = new Example();     

       9.         ex.change(ex.str, ex.ch);     

      10.         System.out.print(ex.str + " and ");     

      11.         System.out.println(ex.ch);     

      12.     }     

      13.     

      14.     public void change(String str, char ch[]) {     

      15.         str = "test ok";     

      16.         ch[0] = 'g';     

      17.     }     

      18. }      

      19. 程序3輸出的是 good and gbc.    

 

 

  20. String 比較特別,看過String 代碼的都知道, String final的。所以值是不變的。 函數中String對象引用的副本指向了另外一個新String對象,而數組對象引用的副本沒有改變,而是改變對象中數據的內容.  

  21. 對于對象類型,也就是Object的子類,如果你在方法中修改了它的成員的值,那個修改是生效的,方法調用結束后,它的成員是新的值,但是如果你把它指向一個其它的對象,方法調用結束后,原來對它的引用并沒用指向新的對象。

 

Java參數,不管是原始類型還是引用類型,傳遞的都是副本(有另外一種說法是傳值,但是說傳副本更好吧,傳值通常是相對傳址而言)。

    如果參數類型是原始類型,那么傳過來的就是這個參數的一個副本,也就是這個原始參數的值,這個跟之前所談的傳值是一樣的。如果在函數中改變了副本的值不會改變原始的值.

    如果參數類型是引用類型,那么傳過來的就是這個shu.html" target="_blank">引用參數的副本,這個副本存放的是參數的地址。如果在函數中沒有改變這個副本的地址,而是改變了地址中的值,那么在函數內的改變會影響到傳入的參數。如果在函數中改變了副本的地址,如new一個,那么副本就指向了一個新的地址,此時傳入的參數還是指向原來的地址,所以不會改變參數的值。

( 對象包括對象引用即地址和對象的內容)

 

a.傳遞值的數據類型:八種基本數據類型和String(這樣理解可以,但是事實上String也是傳遞的地址,只是string對象和其他對象是不同的,string對象是不能被改變的,內容改變就會產生新對象。那么StringBuffer就可以了,但只是改變其內容。不能改變外部變量所指向的內存地址)。

b.傳遞地址值的數據類型:除String以外的所有復合數據類型,包括數組、類和接口

 

下面舉例說明:

Java 應用程序中永遠不會傳遞對象,而只傳遞對象引用。因此是按引用傳遞對象。但重要的是要區分參數是如何傳遞的,這才是該節選的意圖。Java 應用程序按引用傳遞對象這一事實并不意味著 Java 應用程序按引用傳遞參數。參數可以是對象引用,而 Java 應用程序是按值傳遞對象引用的。

Java 應用程序中的變量可以為以下兩種類型之一:引用類型或基本類型。當作為參數傳遞給一個方法時,處理這兩種類型的方式是相同的。兩種類型都是按值傳遞的;沒有一種按引用傳遞。

按值傳遞意味著當將一個參數傳遞給一個函數時,函數接收的是原始值的一個副本。因此,如果函數修改了該參數,僅改變副本,而原始值保持不變。按引用傳遞意味著當將一個參數傳遞給一個函數時,函數接收的是原始值的內存地址,而不是值的副本。因此,如果函數修改了該參數,調用代碼中的原始值也隨之改變。

當傳遞給函數的參數不是引用時,傳遞的都是該值的一個副本(按值傳遞)。區別在于引用。在 C++ 中當傳遞給函數的參數是引用時,您傳遞的就是這個引用,或者內存地址(按引用傳遞)。在 Java 應用程序中,當對象引用是傳遞給方法的一個參數時,您傳遞的是該引用的一個副本(按值傳遞),而不是引用本身。

Java 應用程序按值傳遞所有參數,這樣就制作所有參數的副本,而不管它們的類型。

 

  

Java代碼  收藏代碼

 

    1. class Test  

       2. {  

       3.   public static void main(String args[])  

       4.   {  

       5.     int val;  

       6.     StringBuffer sb1, sb2;  

       7.    

       8.     val = 10;  

       9.     sb1 = new StringBuffer("apples");  

      10.     sb2 = new StringBuffer("pears");  

      11.     System.out.println("val is " + val);  

      12.     System.out.println("sb1 is " + sb1);  

      13.     System.out.println("sb2 is " + sb2);  

      14.     System.out.println("");  

      15.    

      16.     System.out.println("calling ");  

      17.     //按值傳遞所有參數  

      18.     modify(val, sb1, sb2);  

      19.     System.out.println("returned from modify");  

      20.     System.out.println("");  

      21.    

      22.     System.out.println("val is " + val);  

      23.     System.out.println("sb1 is " + sb1);  

      24.     System.out.println("sb2 is " + sb2);  

      25.   }  

      26.    

      27.   public static void modify(int a, StringBuffer r1,  

      28.                             StringBuffer r2)  

      29.   {  

      30.       System.out.println("in modify...");  

      31.       a = 0;  

      32.       r1 = null;  //1  

      33.       r2.append(" taste good");  

      34.       System.out.println("a is " + a);  

      35.       System.out.println("r1 is " + r1);  

      36.       System.out.println("r2 is " + r2);  

      37.   }  

      38. }  

      39.    

      

    Java 應用程序的輸出  

      

       1.    

       2. val is 10  

       3. sb1 is apples  

       4. sb2 is pears  

       5.    

       6. calling modify  

       7. in modify...  

       8. a is 0  

       9. r1 is null  

      10. r2 is pears taste good  

      11. returned from modify  

      12.    

      13. val is 10  

      14. sb1 is apples  

      15. sb2 is pears taste good  

      16.    

 

 

 

 

這段代碼聲明了三個變量:一個整型變量和兩個對象引用。設置了每個變量的初始值并將它們打印出來。然后將所有三個變量作為參數傳遞給 modify 方法。

 

modify 方法更改了所有三個參數的值:

 

將第一個參數(整數)設置為 0。

將第一個對象引用 r1 設置為 null。

保留第二個引用 r2 的值,但通過調用 append 方法更改它所引用的對象(這與前面的 C++ 示例中對指針 p 的處理類似)。

 

當執行返回到 main 時,再次打印出這三個參數的值。正如預期的那樣,整型的 val 沒有改變。對象引用 sb1 也沒有改變。如果 sb1 是按引用傳遞的,正如許多人聲稱的那樣,它將為 null。但是,因為 Java 編程語言按值傳遞所有參數,所以是將 sb1 的引用的一個副本傳遞給了 modify 方法。當 modify 方法在 //1 位置將 r1 設置為 null 時,它只是對 sb1 的引用的一個副本進行了該操作,而不是像 C++ 中那樣對原始值進行操作。

 

另外請注意,第二個對象引用 sb2 打印出的是在 modify 方法中設置的新字符串。即使 modify 中的變量 r2 只是引用 sb2 的一個副本,但它們指向同一個對象。因此,對復制的引用所調用的方法更改的是同一個對象。

傳值---傳遞基本數據類型參數

Java代碼  收藏代碼

 

    public    class           PassValue{  

        static void exchange(int a, int b){//,交換a,b的值  

            int temp;  

            temp = a;  

            a = b;  

            b = temp;  

        }  

        public static void main(String[] args){  

           int i = 10;  

           int j = 100;  

           System.out.println("before call: " + "i=" + i + "\t" + "j = " + j);//調用前  

            exchange(i, j);                                                                    //值傳遞,main方法只能調用靜態方法  

            System.out.println("after call: " + "i=" + i + "\t" + "j = " + j);//調用后  

        }  

    }  

    運行結果:  

            before call: i = 10        j = 100  

            after    call: i = 10        j = 100  

 

 

說明:調用exchange(i, j)時,實際參數i,j分別把值傳遞給相應的形式參數a,b,在執行方法exchange()時,形式參數a,b的值的改變不影響實際參數ij的值,ij的值在調用前后并沒改變。

引用傳遞---對象作為參數

如果在方法中把對象(或數組)作為參數,方法調用時,參數傳遞的是對象的引用(地址),即在方法調用時,實際參數把對對象的引用(地址)傳遞給形式參數。這是實際參數與形式參數指向同一個地址,即同一個對象(數組),方法執行時,對形式參數的改變實際上就是對實際參數的改變,這個結果在調用結束后被保留了下來。

Java代碼  收藏代碼

 

    class Book{  

        String name;  

        private folat price;  

        Book(String n,    float ){                //構造方法  

            name = n;  

            price = p;  

        }  

        static  void  change(Book a_book,    String n,    float p){    //靜態方法,對象作為參數  

                a_book.name = n;  

                a_book.price = p;  

        }  

        public void output(){        //實例方法,輸出對象信息  

            System.out.println("name: " + name + "\t" + "price: " + price);  

        }  

    }  

     public class PassAddr{  

        public static void main(String [] args){  

            Book b = new Book("java2",    32.5f);  

            System.out.print("before call:\t");        //調用前  

            b.output();  

            b.change(b,    "c++",    45.5f);            //引用傳遞,傳遞對象b的引用,修改對象b的值  

            System.out.print("after call:\t");            //調用后  

            b.output();  

        }  

    }  

    運行結果:  

            before    call:    name:java2        price:32.5  

            after       call:    name:c++          price:45.5  

 

 

說明:調用change(b,"c++",45.5f)時,對象b作為實際參數,把引用傳遞給相應的形式參數a_book,實際上a_book也指向同一個對象,即該對象有兩個引用名:ba_book。在執行方法change()時,對形式參數a_book操作就是對實際參數b的操作。


來源:博客園

上一篇: java環境變量配置

下一篇: JVM參數對J2EE性能優化的影響

分享到: 更多
二人麻将赢钱技巧 时时彩计划软件免费版 北京pk赛车开奖直播 3d和数投注中奖金额表 如何在网上开彩票投注站 下载二人斗地主 近30期双色球走势 通比牛牛app下载 江西时时2016出错了 分分快三稳赚不赔技巧 明牌抢庄斗牛技巧最新 新时时走势图怎么不全 网上彩票代理怎么赚钱 北京pk赛车开结果结果 飞艇6码二期免费计划 为什么时时彩先赢后输