[英]Should i implement List interface or extend ArrayList class in Java
[英]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$ArrayList
( Arrays.asList
返回的實現類型)不是java.util.ArrayList
的子類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.