我读过这篇文章: 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()
时会抛出异常?
答案 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()
使用List
或Arrays.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()
。