java.util.Arrays中的私有静态类ArrayList – 为什么?
在java.util.Arrays中,定义了一个名为“ArrayList”的私有静态类。 它仅从Arrays.asList方法引用。
这样做有什么好处? 为什么不引用java.util.ArrayList呢?
代码如下:
/** * @serial include */ private static class ArrayList extends AbstractList implements RandomAccess, java.io.Serializable
这样做有什么好处? 为什么不引用
java.util.ArrayList
呢?
一个原因是实际的实现类不是公共API细节。 这样做意味着他们可以在将来更改实现类…而不会有破坏客户代码的风险。
执行此操作的另一个原因是此私有类以不同于ArrayList的方式实现某些操作。 特别是涉及更改列表大小的操作需要实现以抛出exception…以符合Arrays.asList(...)
方法的javadocs中指定的行为。
实际上, Arrays.asList(...)
返回的列表是原始数组的包装器,而不是完整的函数列表。 这有利有弊:
-
在不利方面,某些操作不起作用。
-
从好的方面来说,创建一个包装器要比从一个数组中创建一流列表要便宜得多。 (后者需要将数组内容复制到列表中……对于大型数组而言,这将是昂贵的。)
此外,还存在这样的问题:通过包装器可以看到对原始数组的更改(反之亦然)……如果您需要它,这可能很有用。
你在评论中问了这个问题:
a)为什么要返回不可resize的列表?
因为返回一个常规的可resize的列表需要在某个时刻复制数组内容……这很昂贵。 (如果实现延迟了复制,直到执行了大小更改操作,原始数组和列表之间的关系将很难理解。想一想……)
b)为什么不使用Collections.unmodifiableList并传递java.util.ArrayList对象?
这没有任何成就。 您仍然必须将数组内容复制到ArrayList
。 这个“奇怪的”行为规范的重点是避免复制的需要。
尽管private static ArrayList
类与java.util.ArrayList
具有相同的名称, 但它们的设计行为却不同 。 鉴于此,没有理由认为实现应该是同一个。
Arrays#asList()
返回由指定数组支持的固定大小的列表。 (对返回列表的更改“直写”到数组。)此方法充当基于数组的API和基于集合的API之间的桥梁。