Java 为什么arraylist 类实现List 并扩展AbstractList?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18558536/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 09:02:16  来源:igfitidea点击:

Why does arraylist class implement List as well as extend AbstractList?

javaarraysarraylist

提问by Ashwin

The implementation of java.util.ArrayListimplements Listas well as extends AbstractList. But in java docs you can see that AbstractList already implements List. Then wouldn't it be redundant to implement List as well as extend AbstractList?
My second question

Please have a look at the following code :

implements和 extends的java.util.ArrayList实现。但是在 java 文档中你可以看到 AbstractList 已经实现了 List。那么实现List和扩展AbstractList不是多余的吗? 我的第二个问题 请看下面的代码:ListAbstractList



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. But this one only extends AbstractList but does not implement List. But the above code compiles.
BUT when the code is modified to the following

Arrays.asList()Arrays 类的方法包含它自己的 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);

I get an error : cannot convert form List<String> to ArrayList<String>
What is the reason behind this?
EDIT
Arrays.asList()does return its own implementation of ArrayList. Check thisout.

我收到一个错误:cannot convert form List<String> to ArrayList<String>
这背后的原因是什么?
EDIT
Arrays.asList()确实返回了它自己的 ArrayList 实现。看看这个

采纳答案by Pshemo

For your first question take a look at Why does ArrayList have "implements List"?

对于你的第一个问题,看看为什么 ArrayList 有“实现列表”?



To answer your second question

回答你的第二个问题

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

as you mentioned Arrays.asListreturns its own implementationof AbstractList and unfortunately creators of this code also named this class ArrayList. Now because we cant cast horizontally but only vertically returned array list can't be cast to java.utli.ArrayListbut only to java.util.AbstractListor its super types like java.util.Listthat is why your first code example works.

正如你所提到的,Arrays.asList它返回了它自己的 AbstractList实现,不幸的是,这段代码的创建者也将这个类命名为 ArrayList。现在因为我们不能水平转换但只有垂直返回的数组列表不能转换为java.utli.ArrayList但只能转换为java.util.AbstractList或它的超类型java.util.List,这就是您的第一个代码示例工作的原因。

回答by Sajal Dutta

Arrays.asListreturns a List. So casting it to ArrayListis not safe as you do not know what type of Listis being returned (depends on the array type it's creating the list from). Your second snippet wants an ArrayListimplicitly. Hence it fails while your first snippet compiles fine because it expects a List. You can do-

Arrays.asList返回一个List。因此,将其转换为ArrayList并不安全,因为您不知道返回的是什么类型的List(取决于它从中创建列表的数组类型)。你的第二个片段需要一个ArrayList隐式。因此,当您的第一个代码段编译正常时它会失败,因为它需要一个List。你可以做-

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

回答by dasblinkenlight

Then wouldn't it be redundant to implement List as well as extend AbstractList?

那么实现List和扩展AbstractList不是多余的吗?

Yes, it is 100% redundant. However, Java implementors added interfaces very consistently in all public implementation of the collections library:

是的,它是 100% 冗余的。但是,Java 实现者在集合库的所有公共实现中都非常一致地添加了接口:

  • LinkedList<E>and ArrayList<E>extend AbstractList<E>which implements List<E>, and then implement List<E>themselves.
  • HashSet<E>and TreeSet<E>extend AbstractSet<E>which implements Set<E>, and then implement Set<E>themselves.
  • HashMap<K,V>and TreeMap<E>extend AbstractMap<K,V>which implements Map<K,V>, and then implement Map<K,V>themselves.
  • 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>自己。

My understanding is that they did so for documentation purposes: the authors wanted to show that ArrayList<E>is primarily a List<E>; the fact that ArrayList<E>extends AbstractList<E>is a less significant detail of its implementation. Same goes for the other public collection types.

我的理解是他们这样做是为了文档目的:作者想表明这ArrayList<E>主要是一个List<E>; 这一事实ArrayList<E>扩展AbstractList<E>是其实施的较显著的细节。其他公共集合类型也是如此。

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>彼此无关。

回答by Evgeniy Dorofeev

1) ArrayList implements Listis redundant but still legal. Only JCF (Java Collection Framework) designers could answer why. 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.

1)ArrayList implements List是多余的,但仍然合法。只有 JCF(Java 集合框架)设计者可以回答为什么。由于首席 JCF 设计师 J.Bloch 没有在“Effective 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 并且不能转换为它

回答by raisercostin

The answer to your first question is that implementing List is a contract. That contract can be defined by both AbstractList and 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.

你的第一个问题的答案是实现 List 是一个契约。该契约可以由 AbstractList 和 ArrayList 定义。ArrayList 实现 List 以发布一个事实,当将来可能有必要不从可能实现或不实现 List 的 AbstractList 扩展时,将尊重 List 契约。

For the second question: Arrays.asList returns a List. It could happen that in the current implementation returns 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.

对于第二个问题:Arrays.asList 返回一个列表。在当前实现中可能会返回 ArrayList。例如,在下一个版本中可以返回一个不同的列表 LinkedList 并且仍然会遵守合同(由方法签名定义)。

回答by dharam

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 Listinterface and provided the ArrayListimplementation for the the Listinterface.

绝对没有理由这样做,但请考虑这种情况,我已经编写了List接口并提供了接口的ArrayList实现List

I have not yet written any abstract class AbstractListtill now.

AbstractList到现在为止我还没有写过任何抽象类。

One day a requirement comes, where I am asked to write few more implementations of the Listinterface where most of them are having similar or same concrete methods for the abstractmethods in Listinterface.

有一天,一个需求出现,在那里我被要求写的几个实现List,其中大部分都是具有相似或相同的具体方法接口abstract中的方法List接口。

I will go ahead and write an AbstractListwith necessary implementation for all those methods. But now I will not like that half of my classes to implement the Listinterface and half of them extending AbstractList.

我将继续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.

此外,我不能只是从我之前编写的类中删除“实现列表”,可能是因为这不是正确的时间,或者我不希望其他人的代码因我的新版本而中断。

NoteThis is solely my opinion.

注意这仅是我的意见。

回答by ceklock

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. But this one only extends AbstractList but does not implement List.

Arrays 类的 Arrays.asList() 方法包含它自己的 ArrayList 实现。但是这个只扩展了 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. 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.

Arrays.asList() 返回一个 List,它可以是任何类型的 List。该代码中实现的ArrayList与java.util.ArrayList的ArrayList不同,它们只是共享相同的名称,但它们不是相同的代码。

回答by Kang

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.asListis List, but does not know its exact implementation which may not be java.util.ArrayList. So you got this compile time error.

编译器只知道Arrays.asListis的返回类型List,但不知道它可能不是的确切实现java.util.ArrayList。所以你得到了这个编译时错误。

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$ArrayListcannot 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.asListreturns) is not a subtype of java.util.ArrayList.

这是因为java.util.Arrays$ArrayListArrays.asList返回的实现类型)不是java.util.ArrayList.