簡體   English   中英

使用Java中的getter方法返回私有集合

[英]Returning a private collection using a getter method in Java

我有許多在內部使用私有集或列表的Java類。 我希望能夠使用get ... List()方法返回這些集/列表。

我正在考慮的替代方案:

  1. 返回對內部對象的引用
  2. 構建一個新的集/列表並填寫它(這似乎是不好的做法?)
  3. 使用Collections.unmodifiableList(partitions);

以下哪一項是解決此問題的最常見/最佳方式?

這里有許多方面需要考慮。 正如其他人已經指出的那樣,最終決定取決於你的意圖,但有關這三個選項的一般性陳述:

1.返回對內部對象的引用

這可能會帶來問題。 當你這樣做時,你幾乎不可能保證一致的狀態。 調用者可能會獲取列表,然后做一些討厭的事情

List<Element> list = object.getList();
list.clear();
list.add(null);
...

也許不是惡意的意圖卻意外,因為他認為這是安全/允許這樣做。


2.構建一個新的集/列表並填寫它(這似乎是不好的做法?)

這不是一般的“壞習慣”。 無論如何,它是API設計方面迄今為止最安全的解決方案。 這里唯一需要注意的是,可能存在性能損失,具體取決於幾個因素。 例如,列表中包含多少元素,以及如何使用返回的列表。 像這樣的一些(可疑的?)模式

for (int i=0; i<object.getList().size(); i++)
{
    Element element = object.getList().get(i);
    ...
}

可能會變得非常昂貴(盡管有人可能會爭辯說,在這種特殊情況下,是否是這樣實現它的用戶的錯, 一般問題仍然有效)


3.使用Collections.unmodifiableList(partitions);

這是我個人經常使用的。 它在API設計意義上是安全的,與復制列表相比,其開銷只有微不足道。 但是,調用者在獲得對它的引用之后知道該列表是否可能發生變化是很重要的。

這導致...


最重要的建議:

記錄方法正在做什么! 不要寫這樣的評論

/** 
 * Returns the list of elements.
 *
 * @return The list of elements. 
 */
public List<Element> getList() { ... }

而是指定您可以確定列表的內容。 例如

/** 
 * Returns a copy of the list of elements...
 */

要么

/** 
 * Returns an unmodifiable view on the list of elements...
 */

就個人而言,我總是在這種文檔的兩個選項之間徘徊:

  • 明確什么方法做的以及它如何被使用
  • 不要暴露或過度指定實現細節

例如,我經常寫這樣的文檔:

/** 
 * Returns an unmodifiable view on the list of elements. 
 * Changes in this object will be visible in the returned list. 
 */

第二句是關於行為的明確而有約束力的陳述。 調用者知道這一點非常重要 對於並發應用程序(和大多數應用程序以某種方式或其他並發),這意味着調用者假設后,他獲得的參考,這可能會導致一個列表可以同時改變ConcurrentModificationException當變化發生時,他正在迭代列表。

但是,這些詳細的規范限制了之后改變實現的可能性。 如果您以后決定返回內部列表的副本,則行為將以不兼容的方式更改。

所以有時候我也明確指出沒有指定行為:

/** 
 * Returns an unmodifiable list of elements. It is unspecified whether 
 * changes in this object will be visible in the returned list. If you
 * want to be informed about changes, you may attach a listener to this 
 * object using this-and-that method...
 */

當您打算創建公共API時,這些問題主要是不重要的。 一旦你以某種方式實現它,人們就會以一種或另一種方式依賴這種行為。

所以回到第一點:它總是取決於你想要達到的目標。

你的決定應該基於一件事(主要是)

  1. 允許其他方法修改原始集合?

    是:返回內部對象的引用。

    1. 構建一個新的集合/列表並填寫它(這似乎是不好的做法? - 不。完全沒有。這被稱為防御性編程並被廣泛使用)。
    2. 使用Collections.unmodifiableList(partitions);
return a reference to the internal object

在這種情況下,接收方端可以修改對象的集合或列表,這可能不是必需的。 如果允許用戶修改對象的狀態,那么這是最簡單的方法。


construct a new set/list and fill it up (this seems bad practice?)

這是示例淺復制,其中集合對象將不可修改,但對象將使用相同。 因此,對象狀態的任何更改都將影響實際的集合。


use Collections.unmodifiableList(partitions);

在這種情況下,它返回指定列表的不可修改的視圖。 此方法允許模塊為用戶提供對內部列表的“只讀”訪問。 在您希望保持對象狀態安全的情況下,這可以用作最佳實踐。

我相信最好的解決方案是返回一個不可修改的列表。 如果與新列表的構造相比較,則返回原始列表的不可修改的“代理”可以使客戶端不會隱式地生成許多不必要的列表。 另一方面,如果客戶端確實需要具有可修改的列表,則讓它自己創建一個新列表。

您仍需要考慮的問題是可能會修改列表中包含的對象。 Java中沒有便宜且簡單的const-correctness。

第二種選擇絕對是正確的選擇。

其他兩個選項取決於您的要求。

  • 如果您不打算修改類外的列表值,請返回不可修改的列表。
  • 否則,只需返回參考。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM