Arrays.asList的返回类型是什么?

时间:2017-05-17 07:52:04

标签: java collections

我读过这篇文章: Difference between Arrays.asList(array) vs new ArrayList<Integer>(Arrays.asList(ia)) in java

我有一个问题。 我看一下这条线:

List<Integer> list2 = Arrays.asList(ia)

仍然有一句话说:

  

当然,包装器上不允许使用某些List操作,例如   添加或删除列表中的元素,您只能阅读或   覆盖元素。

如果list2有List Interface的引用,我希望它能实现Java中List接口中包含的所有方法。 https://docs.oracle.com/javase/7/docs/api/java/util/List.html

  

add(int index,E element)

  

remove(int index)

在List界面中显示,那么怎么可能它们没有在list2中实现?

我原本预计list2列表;因此我可以调用属于List接口的所有方法?!那么为什么在调用add()remove()时会抛出异常?

5 个答案:

答案 0 :(得分:2)

这里有一个细微的细节可能很容易错过:

Arrays.asList() javadoc简要提及:

  

返回由指定数组支持的固定大小的列表。

换句话说:是的,你收到的内容是&#34;我是一个名单&#34 ;;但实际上,底层实现为您提供了一些我们称之为结构不可变列表对象的东西。因此,所有将改变该特定列表的结构的方法......都被禁用&#34; (通过在通话中抛出异常)。您仍然可以通过更改该列表中的元素来呼叫set()

长话短说:此方法的目的 为您提供完全支持List的对象。此方法的目的是让您快速创建已修复&#34;列表&#34;对象

更多的个人意见:我同意,这实际上不是&#34;一致&#34;。我原本预计会返回一个完全不可变的列表;而不是一些半生不熟的&#34; &#34;结构不变的#34;。

答案 1 :(得分:1)

它返回java.util.Arrays.ArrayList的{​​{1}}

不是fixed-size list

答案 2 :(得分:1)

Arrays.asList(ia)方法从扩展AbstractList类的类返回一个对象,而AbstractList类实现List接口。 不幸的是,扩展AbstractList的此类的名称是ArrayList(与我们都知道的公共ArrayList相同的名称-java.util.ArrayList)。不过要小心。此类是Arrays类的 inner 私有静态类,该类的实例由Arrays.asList方法创建并返回。检查类数组here的源代码。因此,此内部私有静态类的路径为java.util.Arrays.ArrayList而不是java.util.ArrayList。尽管它们具有相同的名称,但它们是不同的类,我们不能使用new运算符创建java.util.Arrays.ArrayList,因为它是私有的。仅作为Arrays.asList方法之类的Arrays方法的返回。

因此,正如我们在Arrays源代码中看到的那样,内部私有静态ArrayList类扩展了AbstractList类。 AbstractList类是实现List接口的抽象类。因此,它必须从List接口实现两个重载的add方法。正如我们在AbstractList类的源代码中看到的那样,实现List接口的add(int index,E element)方法,以便始终返回UnsupportedOperationException。

public void add(int index, E element) {
    throw new UnsupportedOperationException();
}

为什么?耐心一点。第二个add(E元素)的实现调用第一个参数作为列表大小的上一个add(int index,E元素)

public boolean add(E e) {
    add(size(), e);
    return true;
}

很荣幸来到这里...我们继续... 如果扩展AbstractList的类(例如Array类的内部ArrayList类)没有覆盖两个继承的add方法,则无论何时调用add方法,都将返回UnsupportedOperationException。 检查Array类的内部ArrayList类的源代码,我们发现没有覆盖的add(int index,E element)方法...

所以... quot eartstrandum

答案 3 :(得分:0)

正如您在Oracle Java doc中看到的那样,文档说Arrays.asList(..)返回一个固定大小的列表。因此,它可以是列表界面的实现,不允许更改列表大小。

答案 4 :(得分:0)

您问题的核心是:

  

如果list2有List接口的引用,我希望它能实现Java中List接口中包含的所有方法。

您说得对,声称是List的任何内容都必须包含List界面中每个方法的实现。但该实现的行为取决于实现。表现良好的实现应该执行List的JavaDoc所做的事情,但是例如List.add()注意:

  

<强>抛出:

     

UnsupportedOperationException - 如果此列表不支持添加操作

这是因为拥有可以迭代和阅读的List通常很有用,但无法添加。有时这是因为它是不可能的 - 例如,列表是对您不具有写访问权限的数据库的视图。有时它是因为它不合逻辑 - 如果你有一份所有四张扑克牌套装的清单,改变它是没有意义的。有时它只是保护程序员,就像final关键字阻止你错误地修改变量一样。 不可变的集合在安全性和可靠的多线程方面具有巨大的优势。

在这种情况下,它是第一个:在Arrays.asList()的限制范围内是不可能的。因为它是数组的List视图,所以您只能对数组执行相同的操作。您无法更改数组的长度,因此您无法对从.add()获得的.remove()使用ListArrays.asList()

一些额外的细节,出于兴趣。

Arrays.asList()的Javadoc并没有告诉你返回对象的具体类是什么;只有它的界面List。这是因为它不属于您的业务,实施可以随意更改。

但是我们可以查看源代码,并看到Arrays.java包含private static class ArrayList<E> extends AbstractList<E>。这是Arrays.asList()返回的内容 - 它与java.util.ArrayList完全不同并且分开。{1}}。它是Arrays专用的,但另一个类可以通过公共接口List使用它。

此实现扩展了AbstractList,其文档包括:

  

要实现不可修改的列表,程序员只需要扩展此类并提供get(int)size()方法的实现。

     

要实现可修改的列表,程序员必须另外覆盖set(int, E)方法(否则会抛出UnsupportedOperationException)。如果列表是可变大小的,程序员必须另外覆盖add(int, E)remove(int)方法。

隐私Arrays.ArrayList不会延伸add()remove()