亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

用于哈希集或其他實現的 Java 變量類型集合?

用于哈希集或其他實現的 Java 變量類型集合?

偶然的你 2022-09-28 15:59:01
我經常在類中看到像字段這樣的聲明。對我來說,使用變量類型的接口來提供實現的靈活性是完全有意義的。上面的示例仍然定義了必須使用哪種s,分別允許哪些操作以及在某些情況下(由于文檔)它應該如何表現。List<String> list = new ArrayList<>();Set<String> set = new HashSet<>();Collection現在考慮這樣一種情況,即實際上只需要(甚至)接口的功能才能在類中使用字段,并且這種實際上并不重要,或者我不想過度指定它。因此,我選擇例如作為實現,并將字段聲明為 。CollectionIterableCollectionHashSetCollection<String> collection = new HashSet<>();在這種情況下,該字段是否應實際屬于類型?這種聲明是不是不好的做法,如果是,為什么?或者,盡可能少地指定實際類型(并且仍然提供所有必需的方法)是一種很好的做法。我問這個問題的原因是因為我幾乎從未見過這樣的聲明,最近我只需要指定接口的功能,我得到了更多。SetCollection例:// Only need Collection features, but decided to use a LinkedListprivate final Collection<Listener> registeredListeners = new LinkedList<>();public void init() {    ExampleListener listener = new ExampleListener();    registerListenerSomewhere(listener);    registeredListeners.add(listener);    listener = new ExampleListener();    registerListenerSomewhere(listener);    registeredListeners.add(listener);}public void reset() {    for (Listener listener : registeredListeners) {        unregisterListenerSomewhere(listener);    }    registeredListeners.clear();}
查看完整描述

3 回答

?
手掌心

TA貢獻1942條經驗 獲得超3個贊

由于您的示例使用私有字段,因此隱藏實現類型并不重要。您(或維護此類的任何人)始終可以查看字段的初始值設定項以查看它是什么。

但是,根據它的使用方式,可能值得為該字段聲明一個更具體的接口。將其聲明為 a 表示允許重復,并且排序很重要。將其聲明為 a 表示不允許重復,并且排序并不重要。您甚至可以將字段聲明為具有特定的實現類(如果其中有重要內容)。例如,將其聲明為 “表示不允許重復項,但排序很重要。ListSetLinkedHashSet

如果類型出現在類的公共 API 中,以及該類的兼容性約束是什么,那么是否使用接口以及使用哪個接口的選擇將變得更加重要。例如,假設有一個方法

public ??? getRegisteredListeners() { 
   return ...
}

現在,返回類型的選擇會影響其他類。如果您可以更改所有呼叫者,也許這沒什么大不了的,您只需要編輯其他文件即可。但假設調用方是一個您無法控制的應用程序?,F在,接口的選擇至關重要,因為您無法在不破壞應用程序的情況下更改它。這里的規則通常是選擇最抽象的接口,以支持您希望調用方想要執行的操作。

大多數 Java SE API 返回 。這提供了從底層實現的相當程度的抽象,但它也為調用方提供了一組合理的操作。調用方可以迭代、獲取大小、執行包含檢查或將所有元素復制到另一個集合。Collection

某些代碼庫用作要返回的最抽象的接口。它所做的只是允許調用方進行迭代。有時這是所有必要的,但與 相比,它可能有些限制。IterableCollection

另一種選擇是返回 .如果您認為調用方可能希望使用流的操作(如篩選、映射、查找等),而不是迭代或使用集合操作,這將非常有用。Stream

請注意,如果選擇返回 或 ,則需要確保返回不可修改的視圖或創建防御性副本。否則,調用方可能會修改類的內部數據,這可能會導致 bug。(是的,即使是可以修改!請考慮獲取 一個,然后調用該方法。如果返回 ,則無需擔心,因為不能使用 來修改基礎源。CollectionIterableIterableIteratorremove()StreamStream

請注意,我將有關字段聲明的問題轉換為有關方法返回類型聲明的問題。有一種“編程到接口”的想法在Java中非常普遍。在我看來,對于局部變量來說,這并不重要(這就是為什么它通??梢允褂茫瑢τ谒接凶侄蝸碚f也無關緊要,因為這些(幾乎)根據定義只影響它們被聲明的類。但是,“程序到接口”原則對于API簽名非常重要,因此在這些情況下,您確實需要考慮接口類型。私人領域,不是那么多。var

(最后一點:有一種情況是,你需要關注私有字段的類型,那就是當你使用一個直接操作私有字段的反射框架時。在這種情況下,您需要將這些字段視為公共字段 - 就像方法返回類型一樣 - 即使它們未聲明。public


查看完整回答
反對 回復 2022-09-28
?
慕的地6264312

TA貢獻1817條經驗 獲得超6個贊

與所有事情一樣,這是一個權衡問題。有兩種對立的力量。

  • 類型越通用,實現的自由度就越高。如果您使用,則可以自由使用 、或,而不會影響用戶/調用方。CollectionArrayListHashSetLinkedList

  • 返回類型越通用,用戶/調用方可用的功能就越少。提供基于索引的查找。A 使得通過 、 和 獲取連續子集變得容易。A 提供了高效的 O(log n) 二進制搜索查找方法。如果您返回 ,則這些都不可用。只能使用最通用的訪問函數。ListSortedSetheadSettailSetsubSetNavigableSetCollection

此外,子類型保證特殊屬性不:s 保存唯一項。已排序。有訂單;它們不是無序的物品袋。如果使用,則用戶/調用方不一定假定這些屬性成立。他們可能被迫進行防御性編碼,例如,即使您知道不會有重復項,也可以處理重復項。CollectionSetSortedSetListCollection

合理的決策過程可能是:

  1. 如果 O(1) 索引訪問得到保證,請使用 。List

  2. 如果元素已排序且唯一,請使用 或 。SortedSetNavigableSet

  3. 如果元素唯一性得到保證,但順序沒有保證,請使用 。Set

  4. 否則,請使用 。Collection


查看完整回答
反對 回復 2022-09-28
?
嚕嚕噠

TA貢獻1784條經驗 獲得超7個贊

這實際上取決于您要對集合對象執行的操作。

Collection<String> cSet = new HashSet<>();
Collection<String> cList = new ArrayList<>();

在這種情況下,如果你愿意,你可以做:

cSet = cList;

但如果你喜歡:

Set<String> cSet = new HashSet<>();

盡管您可以使用構造函數構造新列表,但不允許執行上述操作。

 Set<String> set = new HashSet<>();
 List<String> list = new ArrayList<>();
 list = new ArrayList<>(set);

所以基本上取決于你可以使用的用法或接口。CollectionSet


查看完整回答
反對 回復 2022-09-28
  • 3 回答
  • 0 關注
  • 106 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號