關於Java的=賦值操作和方法傳遞對象時的引用


  

原創:轉載需注明原創地址 https://www.cnblogs.com/fanerwei222/p/11405920.html

 

  下面通過一段代碼和debug結果來展示Java中=操作的賦值改變過程。Test實體類會在最后貼出。

        Test test1 = new Test();
        test1.setKey(1);
        test1.setValue(1);
        Test test4 = new Test();
        test4.setKey(4);
        test4.setValue(4);
        Test test2 = test1;
        test2.setIndex(2);
        test2 = test4;
        test2.setIndex(4);    

  

  結果:

 

  

 

  可以看出:Java的=操作符會將=右側對象實例的地址引用賦值給=左側的對象實例,在被賦值期間,值的改變是怎樣的呢?

  繼續看:  

 

  

  可以看到test1的index值是改變了的,test4的index值也是改變了的,test2首先是test1的引用,在引用test1的時候改變test2的值,test1的值也會相應改變,說明在引用期間所有的改變都是針對實際內存地址操作的,而不是單純針對該對象的值進行改變。

  接下來,我們再看一下方法傳遞時候的引用是怎么改變的:

  先貼上兩個傳入test參數並且在方法內嘗試改變index值的方法:

  

    /**
     * 嘗試直接改變test的index值
     * @param test
     */
    public static void tryInChangeIndex(Test test){
        test.setIndex(123);
    }

    /**
     * 嘗試間接改變test的index值
     * @param test
     */
    public static void tryLinkChangeIndex(Test test){
        Test testLink = new Test();
        testLink = test;
        testLink.setIndex(456);
    }

 

  結果:

 

  

  毫無疑問,成功改變test1的值。

  再看下一個方法:

  

  同樣可以改變,沒有問題。

  再看看String傳遞是怎么回事;

  先貼嘗試改變String的兩個方法:

 

    /**
     * 嘗試改變string的值
     * @param str
     */
    public static void tryChangeString(String str){
        str = "hello new str value";
    }

    /**
     * 嘗試改變string的值方法2
     * @param str
     */
    public static void tryChangeStringTwo(String str){
        String newStr = str;
        newStr = "world in this place";
    }
    String str1 = "good nice";
    String str2 = "i'm iron man";
    tryChangeString(str1);
    tryChangeStringTwo(str2);    

  debug結果:

   

  

  從這里可以看出,方法里面的str值是有改變的,但是方法外str1的值依然是“good nice”,這說明傳入的String 類型是不能被改變的。

  繼續看下面這個方法:

  

  同樣的,在方法里面,雖然把str指向了newStr,並且給newStr賦了新的值,但是str的值依然是沒有變化的,我們再看一下str2的值: 

  

  str2的值也是沒有被改變。

  我猜測: 這是因為參數方法在參數列表這里的String str 重新創建了一個實例,而且將該實例的內存引用地址指向了str2的內存引用地址,所以值會相等,但是當對str進行賦值操作的時候,會重新new String,也就是重新開辟一塊內存空間去存放這個新的值,並且str會指向這塊內存地址,所以改變str的值是無法改變str2的值的,因為它倆根本就不是同一個實例,只是指向了相同的內存引用地址而已.

  *** String 是final類,不可被繼承, 但是String如果實例化的時候沒有定義為final變量,還是可以重新賦值的!編譯器不會報錯!注意區別 final類和final變量.

  再來看一種情況:

        TestFather father = new TestFather();
        Test son = new Test();
        son.setIndex(123456);
        father.setSon(son);
        son.setIndex(789);    

  這種情況下,father里面的son值會怎么變化?debug看一下

  

  到了72行,72行還沒執行的之后,father的son的index值還是123456的,再往下走一步:

 

  BOOM!!! Every thing is diffrent   

 

  

  很明顯,son變了,father擁有的只是son的一個引用,擁有了son的身體卻沒有son的靈魂,這里涉及到一個深拷貝和淺拷貝的問題,有興趣可以自行Google或者Baidu。

  Test.java文件  

package entity;

/**
 * 測試實體類
 */
public class Test {
    private int key;
    private int value;
    private int index;

    //getter setter 省略        
}

  TestFather.java

 

package entity;

/**
 * Test的father
 */
public class TestFather {
    private int num;
    private Test son;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public Test getSon() {
        return son;
    }

    public void setSon(Test son) {
        this.son = son;
    }
}

 

  結束🔚

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM