簡體   English   中英

ArrayList 的區別<Integer>列表 = 新的 ArrayList<Integer> (); 和收藏<Integer> list1 = 新的 ArrayList<Integer> ();

[英]Difference between ArrayList<Integer> list = new ArrayList<Integer>(); and Collection<Integer> list1 = new ArrayList<Integer>();

我不明白以下之間的區別:

  1. ArrayList<Integer> list = new ArrayList<Integer>();
  2. Collection<Integer> list1 = new ArrayList<Integer>();

ArrayList擴展類,它實現的接口Collection ,因此類ArrayList實現Collection接口。 也許list1允許我們使用Collection接口中的靜態方法?

接口沒有靜態方法 [在 Java 7 中]。 list1只允許訪問Collection的方法,而list允許訪問ArrayList所有方法。


最好使用其最不特定的可能類型聲明變量。 因此,例如,如果出於任何原因將ArrayList更改為LinkedListHashSet ,則不必重構大部分代碼(例如,客戶端類)。

想象一下你有這樣的東西(僅用於說明目的,不可編譯):

class CustomerProvider {
    public LinkedList<Customer> getAllCustomersInCity(City city) {
        // retrieve and return all customers for that city
    }
}

然后你決定實現它返回一個HashSet 也許有一些客戶端類依賴於您返回LinkedList的事實,並調用HashSet沒有的方法(例如LinkedList.getFirst() )。

這就是為什么你最好這樣做:

class CustomerProvider {
    public Collection<Customer> getAllCustomersInCity(City city) {
        // retrieve and return all customers for that city
    }
}

我們在這里處理的是interfaceimplementation之間的區別。

接口是一組方法,不考慮這些方法是如何實現的。 當我們將一個對象實例化為具有實際上是interface的類型時,我們所說的是它是一個實現該interface所有方法的對象……但不提供對任何interface訪問class中實際提供這些實現的方法。

當你實例與實施的類型的對象class ,那么你就可以訪問所有這一切的相關方法class 由於class正在實現interface ,您可以訪問接口中指定的方法,以及實現類提供的任何額外功能。

你為什么想做這個? 好吧,通過將對象的類型限制為interface ,您可以切換新的實現而無需擔心更改其余代碼。 這使它變得更加靈活。

正如其他人所說,不同之處在於,當您將Collection接口指定為變量類型時,您只能使用Collection接口定義的方法。 但這並不能回答您為什么要這樣做的問題。

原因是數據類型的選擇為使用代碼的人提供了信息。 特別是用作函數的參數或返回類型時(外部程序員可能無法訪問內部結構)。

按照具體順序,以下是不同類型選擇可能會告訴您的信息:

  • Collection - 一組對象,沒有進一步的保證。 這個對象的使用者可以迭代集合(不保證迭代順序),並且可以了解它的大小,但不能做任何其他事情。
  • List - 一組具有特定順序的對象。 當您迭代這些對象時,您將始終以相同的順序獲得它們。 您還可以通過索引從集合中檢索特定項目,但您不能對此類檢索的性能做出任何假設。
  • ArrayList - 一組具有特定順序的對象,可以在恆定時間內通過索引訪問。

盡管您沒有詢問它們,但這里有一些其他集合類:

  • Set一組保證每個equals()方法不包含重復項的對象。 無法保證這些對象的迭代順序。
  • SortedSet一組不包含重復項的對象,並且將始終以特定順序迭代(盡管集合不保證該特定順序)。
  • TreeSet一組沒有重復的有序對象,表現出O(logN)插入和檢索時間。
  • HashSet一組沒有重復的對象,沒有固有的順序,但提供(攤銷)恆定時間訪問。

唯一的區別是您通過 Collection 接口提供對 list1 的訪問,而您通過 ArrayList 接口提供對 list2 的訪問。 有時,通過受限制的接口提供訪問是有用的,因為它促進了封裝並減少了對實現細節的依賴。

當您對“list1”執行操作時,您將只能從 Collection 接口訪問方法(get、size 等)。 通過將“list”聲明為 ArrayList,您可以訪問僅在 ArrayList 類中定義的其他方法(例如,ensureCapacity 和 trimToSize。

將變量聲明為您需要的最不具體的類通常是最佳實踐。 因此,如果您只需要 Collection 中的方法,請使用它。 通常在這種情況下,這意味着使用 List,它讓您知道它是有序的並且可以處理重復項。

使用最不具體的類/接口允許您以后自由更改實現。 例如,如果您后來了解到 LinkedList 將是一個更好的實現,那么如果您將變量定義為 List,則可以在不破壞所有代碼的情況下更改它。

暫無
暫無

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

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