Java 中的类型列表与 ArrayList 类型
(1) List<?> myList = new ArrayList<?>();
(2) ArrayList<?> myList = new ArrayList<?>();
我知道使用(1),List接口的实现可以交换。似乎(1)通常用于应用程序,而不管是否需要(我自己总是使用它)。
我想知道是否有人使用(2)?
此外,这种情况多久需要使用(1)而不是(2)(即(2)不够。除了编码到接口和最佳实践等)
(1) List<?> myList = new ArrayList<?>();
(2) ArrayList<?> myList = new ArrayList<?>();
我知道使用(1),List接口的实现可以交换。似乎(1)通常用于应用程序,而不管是否需要(我自己总是使用它)。
我想知道是否有人使用(2)?
此外,这种情况多久需要使用(1)而不是(2)(即(2)不够。除了编码到接口和最佳实践等)
几乎总是优先选择,因为例如,可以转换为LinkedList
而不会影响代码库的其余部分。List
ArrayList
List
如果使用 一个而不是 ,则很难将实现更改为一个,因为在代码库中使用了特定的方法,这些方法也需要重构。ArrayList
List
ArrayList
LinkedList
ArrayList
您可以在此处阅读有关实现的信息。List
您可以从 开始,但很快就会发现另一个实现是更合适的选择。ArrayList
我想知道是否有人使用(2)?
是的。但很少出于合理的理由(IMO)。
人们被烧伤,因为他们在应该使用的时候使用:ArrayList
List
实用工具方法(如 或不返回 .Collections.singletonList(...)
Arrays.asList(...)
ArrayList
API 中的方法不保证返回相同类型的列表。List
例如,有人被烧伤,https://stackoverflow.com/a/1481123/139985 海报在“切片”方面存在问题,因为没有返回...他将自己的代码设计为用作所有列表变量的类型。他最终通过将子列表复制到新的列表中来“解决”问题。ArrayList.sublist(...)
ArrayList
ArrayList
ArrayList
您需要知道行为方式的论点在很大程度上通过使用标记接口来解决。是的,它有点笨拙,但另一种选择更糟。List
RandomAccess
此外,这种情况实际需要使用(1)而不是(2)的频率(即(2)不够的地方)。除了“编码到接口”和最佳实践等)
这个问题的“频率”部分客观上是无法回答的。
(我能举个例子吗)
有时,应用程序可能要求您在 API 中使用 API 中没有的方法。例如,或 。(最后一个只有在您创建了 ArrayList 的子类型,该子类型将方法声明为 .)ArrayList
List
ensureCapacity(int)
trimToSize()
removeRange(int, int)
public
这是编码到类而不是接口IMO的唯一合理原因。
(从理论上讲,您可能会在性能方面略有提高...在某些情况下...在某些平台上...但除非你真的需要最后的0.05%,否则不值得这样做。这不是一个合理的理由,IMO。
如果您不知道随机访问是否有效,则无法编写有效的代码。
这是一个有效的观点。但是,Java提供了更好的方法来解决这个问题。例如:
public <T extends List & RandomAccess> void test(T list) {
// do stuff
}
如果使用未实现的列表调用它,则会收到编译错误。RandomAccess
您还可以动态测试...用。。。如果静态键入太尴尬。您甚至可以编写代码以使用不同的算法(动态),具体取决于列表是否支持随机访问。instanceof
请注意,这不是实现 的唯一列表类。其他包括 和 。ArrayList
RandomAccess
CopyOnWriteList
Stack
Vector
我看到人们提出同样的论点(因为没有实现它)......但上面的方法也解决了这个问题。(在某种程度上,它可以使用运行时类型来解决。如果任何元素不可序列化,则 序列化将失败。Serializable
List
ArrayList
最后,我不会说“因为它是好的风格”。这个“理由”既是一个循环论证(“为什么它是'好风格'?”),也是对一个未声明的(可能不存在的!)更高权威的呼吁(“谁说它是'好风格'?”)。
(我确实认为编程到界面是很好的风格,但我不会以此为理由。您最好了解真正的原因并为自己得出(IMO)正确的结论。正确的结论可能并不总是相同的...取决于上下文。