簡體   English   中英

為什么arraylist類實現List以及擴展AbstractList?

[英]Why does arraylist class implement List as well as extend AbstractList?

java.util.ArrayList實現實現了List以及擴展AbstractList 但是在java文檔中你可以看到AbstractList已經實現了List。 那么實現List以及擴展AbstractList不是多余的嗎?
我的第二個問題

請看下面的代碼:

String str = "1,2,3,4,5,6,7,8,9,10";
String[] stra = str.split(",");
List<String> a = Arrays.asList(stra);

Arrays類的Arrays.asList()方法包含自己的ArrayList實現。 但是這個只擴展了AbstractList,但沒有實現List。 但上面的代碼編譯。
但是當代碼被修改為以下內容時

String str = "1,2,3,4,5,6,7,8,9,10";
String[] stra = str.split(",");
java.util.ArrayList<String> a = Arrays.asList(stra);

我收到一個錯誤: cannot convert form List<String> to ArrayList<String>
這背后的原因是什么?
編輯
Arrays.asList()確實返回自己的ArrayList實現。 看看這個

那么實現List以及擴展AbstractList不是多余的嗎?

是的,它是100%多余的。 但是,Java實現者在集合庫的所有公共實現中非常一致地添加了接口:

  • LinkedList<E>ArrayList<E>擴展AbstractList<E> ,它實現List<E> ,然后自己實現List<E>
  • HashSet<E>TreeSet<E>擴展AbstractSet<E> ,它實現了Set<E> ,然后自己實現Set<E>
  • HashMap<K,V>TreeMap<E>擴展AbstractMap<K,V> ,它實現Map<K,V> ,然后自己實現Map<K,V>

我的理解是他們這樣做是出於文檔目的:作者希望表明ArrayList<E>主要是List<E> ; ArrayList<E>擴展AbstractList<E>這一事實是其實現的一個不太重要的細節。 其他公共收藏類型也是如此。

請注意, Arrays.ArrayList<E>類不是公開可見的,因此其作者並不關心顯式包含List<T>

對於失敗的轉換,這應該不足為奇,因為內部類Arrays.ArrayList<E>和公共類ArrayList<E>彼此無關。

關於你的第一個問題,看看為什么ArrayList有“實現List”?


回答你的第二個問題

java.util.ArrayList<String> a = Arrays.asList(stra);

正如您所提到的, Arrays.asList返回其自己的AbstractList 實現 ,不幸的是,此代碼的創建者也將此類命名為ArrayList。 現在因為我們不能水平投射但只有垂直返回的數組列表不能轉換為java.utli.ArrayList而只能轉換為java.util.AbstractList或其超類型如java.util.List ,這就是你的第一個代碼示例工作的原因。

Arrays.asList返回一個List 因此,將它轉換為ArrayList是不安全的,因為您不知道返回什么類型的List (取決於它從中創建列表的數組類型)。 你的第二個片段隱含地想要一個ArrayList 因此,當您的第一個代碼段編譯正常時它會失敗,因為它需要一個List 你可以做-

ArrayList<String> a = new ArrayList<String>(Arrays.asList(stra));

1) ArrayList implements List是多余的但仍然合法。 只有JCF(Java Collection Framework)設計師才能回答原因。 由於領導JCF設計師J.Bloch沒有說明為什么在“有效Java”中它是這樣的,似乎我們永遠不會知道為什么。

2)Arrays.asList返回

public class Arrays {
   ...

    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
...

它不是java.util.ArrayList,也不能強制轉換為它

第一個問題的答案是實施List是一份合同。 該合約可以由AbstractList和ArrayList定義。 ArrayList實現了List,以便在將來可能需要擴展而不是可能實現或不實現List的AbstractList時,發布將遵守List契約的事實。

對於第二個問題:Arrays.asList返回一個List。 可能會發生在當前實現中返回ArrayList。 在下一個版本中可以返回一個不同的列表LinkedList,例如,合同(由方法簽名定義)仍然會得到尊重。

我相信,有一個原因。 這只是我的想法,我沒有在JLS的任何地方找到它。

如果我是一名正在編寫廣泛使用的API的開發人員,為什么我會這樣做呢?

我們絕對沒有理由這樣做的,但考慮到這種情況,在那里我已經寫了List界面和提供ArrayList的執行List界面。

到目前為止,我還沒有編寫任何抽象類AbstractList

有一天,一個需求出現,在那里我被要求寫的幾個實現List ,其中大部分都是具有相似或相同的具體方法接口abstract的方法List界面。

我將繼續編寫一個AbstractList其中包含所有這些方法的必要實現。 但是現在我不希望我的一半類實現List接口,其中一半擴展AbstractList

此外,我不能只從我之前寫的類中刪除'implements List`,可能是因為這不是正確的時間,或者我不希望其他代碼與我的新版本中斷。

注意這完全是我的意見。

在我的回答中,我會簡單直接。

實現List以及擴展AbstractList不是多余的嗎?

是的,它是,但他們只是為了澄清代碼,很容易看到該類實現了List接口。

Arrays類的Arrays.asList()方法包含自己的ArrayList實現。 但是這個只擴展了AbstractList,但沒有實現List。

如您所見,這是多余的,如果AbstractList已經聲明了該實現,則不需要重新聲明List接口的實現。

我收到一個錯誤:無法將表單List轉換為ArrayList這背后的原因是什么?

Arrays.asList()返回一個List,它可以是任何類型的List。 在該代碼中實現的ArrayList與java.util.ArrayList的ArrayList不同,它們只是共享相同的名稱,但它們不是相同的代碼。

只是想補充問題2的答案

java.util.ArrayList<String> a=Arrays.asList(stra);

編譯器只知道Arrays.asList的返回類型是List ,但不知道它的確切實現,可能不是java.util.ArrayList 所以你得到了這個編譯時錯誤。

類型不匹配:無法從List轉換為ArrayList

你可以像這樣明確強迫上部演員,

java.util.ArrayList<String> a =(java.util.ArrayList<String>)Arrays.asList(stra);

代碼將成功編譯,但會發生運行時異常,

java.lang.ClassCastException: java.util.Arrays $ ArrayList無法強制轉換為java.util.ArrayList

這是因為java.util.Arrays$ArrayListArrays.asList返回的實現類型)不是java.util.ArrayList的子類型。

暫無
暫無

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

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