简体   繁体   English

为什么arraylist类实现List以及扩展AbstractList?

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

The implementation of java.util.ArrayList implements List as well as extends AbstractList . java.util.ArrayList实现实现了List以及扩展AbstractList But in java docs you can see that AbstractList already implements List. 但是在java文档中你可以看到AbstractList已经实现了List。 Then wouldn't it be redundant to implement List as well as extend AbstractList? 那么实现List以及扩展AbstractList不是多余的吗?
My second question 我的第二个问题

Please have a look at the following code : 请看下面的代码:

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

The Arrays.asList() method of the Arrays class contains its own implementation of ArrayList. Arrays类的Arrays.asList()方法包含自己的ArrayList实现。 But this one only extends AbstractList but does not implement List. 但是这个只扩展了AbstractList,但没有实现List。 But the above code compiles. 但上面的代码编译。
BUT when the code is modified to the following 但是当代码被修改为以下内容时

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

I get an error : cannot convert form List<String> to ArrayList<String> 我收到一个错误: cannot convert form List<String> to ArrayList<String>
What is the reason behind this? 这背后的原因是什么?
EDIT 编辑
Arrays.asList() does return its own implementation of ArrayList. Arrays.asList()确实返回自己的ArrayList实现。 Check this out. 看看这个

Then wouldn't it be redundant to implement List as well as extend AbstractList? 那么实现List以及扩展AbstractList不是多余的吗?

Yes, it is 100% redundant. 是的,它是100%多余的。 However, Java implementors added interfaces very consistently in all public implementation of the collections library: 但是,Java实现者在集合库的所有公共实现中非常一致地添加了接口:

  • LinkedList<E> and ArrayList<E> extend AbstractList<E> which implements List<E> , and then implement List<E> themselves. LinkedList<E>ArrayList<E>扩展AbstractList<E> ,它实现List<E> ,然后自己实现List<E>
  • HashSet<E> and TreeSet<E> extend AbstractSet<E> which implements Set<E> , and then implement Set<E> themselves. HashSet<E>TreeSet<E>扩展AbstractSet<E> ,它实现了Set<E> ,然后自己实现Set<E>
  • HashMap<K,V> and TreeMap<E> extend AbstractMap<K,V> which implements Map<K,V> , and then implement Map<K,V> themselves. HashMap<K,V>TreeMap<E>扩展AbstractMap<K,V> ,它实现Map<K,V> ,然后自己实现Map<K,V>

My understanding is that they did so for documentation purposes: the authors wanted to show that ArrayList<E> is primarily a List<E> ; 我的理解是他们这样做是出于文档目的:作者希望表明ArrayList<E>主要是List<E> ; the fact that ArrayList<E> extends AbstractList<E> is a less significant detail of its implementation. ArrayList<E>扩展AbstractList<E>这一事实是其实现的一个不太重要的细节。 Same goes for the other public collection types. 其他公共收藏类型也是如此。

Note that Arrays.ArrayList<E> class is not publicly visible, so its authors did not care to include List<T> explicitly. 请注意, Arrays.ArrayList<E>类不是公开可见的,因此其作者并不关心显式包含List<T>

As far as the failed conversion goes, this should come as no surprise, because the inner class Arrays.ArrayList<E> and the public class ArrayList<E> are unrelated to each other. 对于失败的转换,这应该不足为奇,因为内部类Arrays.ArrayList<E>和公共类ArrayList<E>彼此无关。

For your first question take a look at Why does ArrayList have "implements List"? 关于你的第一个问题,看看为什么ArrayList有“实现List”?


To answer your second question 回答你的第二个问题

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

as you mentioned Arrays.asList returns its own implementation of AbstractList and unfortunately creators of this code also named this class ArrayList. 正如您所提到的, Arrays.asList返回其自己的AbstractList 实现 ,不幸的是,此代码的创建者也将此类命名为ArrayList。 Now because we cant cast horizontally but only vertically returned array list can't be cast to java.utli.ArrayList but only to java.util.AbstractList or its super types like java.util.List that is why your first code example works. 现在因为我们不能水平投射但只有垂直返回的数组列表不能转换为java.utli.ArrayList而只能转换为java.util.AbstractList或其超类型如java.util.List ,这就是你的第一个代码示例工作的原因。

Arrays.asList returns a List . Arrays.asList返回一个List So casting it to ArrayList is not safe as you do not know what type of List is being returned (depends on the array type it's creating the list from). 因此,将它转换为ArrayList是不安全的,因为您不知道返回什么类型的List (取决于它从中创建列表的数组类型)。 Your second snippet wants an ArrayList implicitly. 你的第二个片段隐含地想要一个ArrayList Hence it fails while your first snippet compiles fine because it expects a List . 因此,当您的第一个代码段编译正常时它会失败,因为它需要一个List You can do- 你可以做-

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

1) ArrayList implements List is redundant but still legal. 1) ArrayList implements List是多余的但仍然合法。 Only JCF (Java Collection Framework) designers could answer why. 只有JCF(Java Collection Framework)设计师才能回答原因。 Since the lead JCF designer J.Bloch does not say why it's like this in "Effective Java" it seems we will never know why. 由于领导JCF设计师J.Bloch没有说明为什么在“有效Java”中它是这样的,似乎我们永远不会知道为什么。

2) Arrays.asList returns 2)Arrays.asList返回

public class Arrays {
   ...

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

it's not java.util.ArrayList and it cannot be cast to it 它不是java.util.ArrayList,也不能强制转换为它

The answer to your first question is that implementing List is a contract. 第一个问题的答案是实施List是一份合同。 That contract can be defined by both AbstractList and ArrayList. 该合约可以由AbstractList和ArrayList定义。 ArrayList implements List to publish the fact that will respect the List contract in the future when it might be necessary to extend not from AbstractList that may or may not implement a List. ArrayList实现了List,以便在将来可能需要扩展而不是可能实现或不实现List的AbstractList时,发布将遵守List契约的事实。

For the second question: Arrays.asList returns a List. 对于第二个问题:Arrays.asList返回一个List。 It could happen that in the current implementation returns ArrayList. 可能会发生在当前实现中返回ArrayList。 In the next version could return a different list LinkedList for example and the contract(defined by the method signature) will still be respected. 在下一个版本中可以返回一个不同的列表LinkedList,例如,合同(由方法签名定义)仍然会得到尊重。

I believe, there is a reason. 我相信,有一个原因。 This is just my thought and I didn't find it anywhere in JLS. 这只是我的想法,我没有在JLS的任何地方找到它。

If I am a developer who is writing an API which is to be widely used, why will I do this? 如果我是一名正在编写广泛使用的API的开发人员,为什么我会这样做呢?

There is absolutely no reason of doing this, but consider this scenario, where I have written the List interface and provided the ArrayList implementation for the the List interface. 我们绝对没有理由这样做的,但考虑到这种情况,在那里我已经写了List界面和提供ArrayList的执行List界面。

I have not yet written any abstract class AbstractList till now. 到目前为止,我还没有编写任何抽象类AbstractList

One day a requirement comes, where I am asked to write few more implementations of the List interface where most of them are having similar or same concrete methods for the abstract methods in List interface. 有一天,一个需求出现,在那里我被要求写的几个实现List ,其中大部分都是具有相似或相同的具体方法接口abstract的方法List界面。

I will go ahead and write an AbstractList with necessary implementation for all those methods. 我将继续编写一个AbstractList其中包含所有这些方法的必要实现。 But now I will not like that half of my classes to implement the List interface and half of them extending AbstractList . 但是现在我不希望我的一半类实现List接口,其中一半扩展AbstractList

Also, I cannot just go and remove the 'implements List` from the classes I wrote earlier, might be because this is not the right time or I do not want other's code to break with my new release. 此外,我不能只从我之前写的类中删除'implements List`,可能是因为这不是正确的时间,或者我不希望其他代码与我的新版本中断。

Note This is solely my opinion. 注意这完全是我的意见。

I will be simple and direct in my answers. 在我的回答中,我会简单直接。

wouldn't it be redundant to implement List as well as extend AbstractList? 实现List以及扩展AbstractList不是多余的吗?

Yes, it is, but they did it just to clarify the code, to be easy to see that the class implements List interface. 是的,它是,但他们只是为了澄清代码,很容易看到该类实现了List接口。

The Arrays.asList() method of the Arrays class contains its own implementation of ArrayList. Arrays类的Arrays.asList()方法包含自己的ArrayList实现。 But this one only extends AbstractList but does not implement List. 但是这个只扩展了AbstractList,但没有实现List。

As you could see, that was redundant, you don't need to re-declare the implementation of List interface if AbstractList already declares that implementation. 如您所见,这是多余的,如果AbstractList已经声明了该实现,则不需要重新声明List接口的实现。

I get an error : cannot convert form List to ArrayList What is the reason behind this? 我收到一个错误:无法将表单List转换为ArrayList这背后的原因是什么?

Arrays.asList() returns a List, it could be any type of List. Arrays.asList()返回一个List,它可以是任何类型的List。 The ArrayList implemented in that code is not the same ArrayList of java.util.ArrayList, they just share the same name, but they are not the same code. 在该代码中实现的ArrayList与java.util.ArrayList的ArrayList不同,它们只是共享相同的名称,但它们不是相同的代码。

just wanna to complement answers to question 2 只是想补充问题2的答案

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

compiler just knows the return type of Arrays.asList is List , but does not know its exact implementation which may not be java.util.ArrayList . 编译器只知道Arrays.asList的返回类型是List ,但不知道它的确切实现,可能不是java.util.ArrayList So you got this compile time error. 所以你得到了这个编译时错误。

Type mismatch: cannot convert from List to ArrayList 类型不匹配:无法从List转换为ArrayList

you can force an upper cast explicitly like this, 你可以像这样明确强迫上部演员,

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

The code will compile successfully, but a runtime exception will happen, 代码将成功编译,但会发生运行时异常,

java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayList java.lang.ClassCastException: java.util.Arrays $ ArrayList无法强制转换为java.util.ArrayList

this is because java.util.Arrays$ArrayList (the type of implemenation which Arrays.asList returns) is not a subtype of 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