1. 程式人生 > 程式設計 >Java返回可變引用物件問題整理

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返回可變引用物件問題整理

但一個物件變數並沒有實際包含一個物件,而僅僅引用一個物件。

在 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。這樣會建立一個當前物件的副本,而不會對當前物件造成影響。

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如何實現不可變類 Class需要用final修飾,保證類不能被繼承所有成員變數需要private修飾,保證成員變數不能直接被訪問類中不允許提供setter方法,保證成員變數不會被改變在getter方法中不能返回物件本身,返回物件的拷貝

到此這篇關於Java返回可變引用物件問題整理的文章就介紹到這了,更多相關Java返回可變引用物件問題內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!