Java 返回可變引用對象的相關問題


1.問題

/**
 * 輸出: Mon Apr 26 10:54:10 CST 2010
 *       Mon Apr 26 10:54:10 CST 2010
 */
public static void main(String[] args){
    Example test = new Example(new Date());

    Date d = test.getDate();
    double tenYearsInMillisSeconds = 10 * 365.25 * 24 * 3600 * 1000;
    d.setTime((long) (d.getTime() - tenYearsInMillisSeconds));

    System.out.println(d);
    System.out.println(test.getDate());
}

public class Example {
    private Date date;

    public Example(Date date){
        this.date = date;
    }

    public Date getDate() {
        return date;
    }
}

Date類破壞了Example的封裝,導致修改實例 d時影響了 test 的值,原因是Date類生成的對象是可變的。

2.對象與對象變量

Date birthday = new Date();
Date deadline = birthday;

這兩個變量引用同一個對象(請參見圖 4-4 )。

一個對象變量並沒有實際包含一個對象,而僅僅引用一個對象。

在 Java 中,任何對象變量的值都是對存儲在另外一個地方的一個對象的引用。new 操作符的返回值也是一個引用。

Date birthday = new Date();可以理解為new Date() 構造了一個 Date 類型的對象, 並且它的值是對新創建對象的引用。這個引用存儲在變量 birthday中。

Java 對象變量與 C++ 的引用並不同

可以將 Java 的對象變量看作 C++ 的對象指針。例如,

Date birthday; // Java

實際上,等同於

Date* birthday; // C++

所有的 Java 對象都存儲在堆中。 當一個對象包含另一個對象變量時, 這個變量依然

包含着指向另一個堆對象的指針。

3.更改器方法與訪問器方法

上文還是沒有解釋清楚為什么Date類的對象是可變對象,原因在這。

假設在上文中Example類中使用Java中與Date類相近的LocalDate類便不會出現上述情況,測試可以自己去嘗試。

原因在於假設使用LocalDate類中的plusDays 方法來修改對象變量,它會生成一個新的LocalDate對象,然后把這個新對象賦值給調用者,原來的對象不做任何改動。

此類只訪問對象而不修改對象的方法有時稱為訪問器方法(accessor method)

而像Date類中的setTime方法會使得原對象的狀態發生改變,此類稱為更改器方法(mutator method)

4.解決方法

如果需要返回一個可變數據域的拷貝,就應該使用 clone。這樣會創建一個當前對象的副本,而不會對當前對象造成影響。
有關 clone 的進一步講解 Java 淺拷貝和深拷貝

public class Example {
    private Date date;

    public Example(Date date){
        this.date = date;
    }

    public Date getDate() {
	return (Date) date.clone();
    }
}

5.不可變類

5.1什么是不可變類

不可變類指當類被實例化后,該類的成員變量均不可被改變。

如JDK內部自帶的很多不可變類IntergerLongBooleanString等。

5.2優缺點

  • 優點:1.線程安全 2.易於構造、使用和測試 3.可以被自由地共享
  • 缺點:對於每一個不同的值都需要對應一個單獨的對象

5.3如何實現不可變類

  1. Class需要用final修飾,保證類不能被繼承
  2. 所有成員變量需要private修飾,保證成員變量不能直接被訪問
  3. 類中不允許提供setter方法,保證成員變量不會被改變
  4. getter方法中不能返回對象本身,返回對象的拷貝


免責聲明!

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



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