在Java中的类型List和类型ArrayList的比较

13 浏览
0 Comments

在Java中的类型List和类型ArrayList的比较

这个问题已经在这里有了答案

“以接口为编程”是什么意思?

(1) List<?> myList = new ArrayList<?>();
(2) ArrayList<?> myList = new ArrayList<?>();

我知道使用(1),可以交换 List 接口的实现。看起来无论是否需要,(1)都通常用于应用程序(我自己总是这样使用)。

我想知道是否有人使用(2)?

另外,有多少情况实际上需要使用(1)而不是(2)(即在(2)不足以满足的情况下..除了编码到接口最佳实践等方面)。

admin 更改状态以发布 2023年5月24日
0
0 Comments

我想知道是否有人使用(2)?

是的。但很少有一个好的理由(在我看来)。

人们会因为使用ArrayList而被烧伤,而他们应该使用List:

  • Collections.singletonList(...)Arrays.asList(...)这样的实用程序方法不会返回ArrayList

  • List API中的方法不保证返回相同类型的列表。

举个例子,一个人在https://stackoverflow.com/a/1481123/139985中有问题,因为ArrayList.sublist(...)不返回ArrayList...而他设计他的代码来使用ArrayList作为他所有列表变量的类型。最后,他通过将子列表复制到新的ArrayList中来“解决”这个问题。

认为你需要知道List如何运行的论点可以通过使用RandomAccess标记界面在很大程度上得到解决。是的,这有点笨拙,但是替代品更糟糕。

此外,什么情况下实际上需要使用(1)而不是(2)(即在不考虑“编码到接口”和最佳实践等方面,(2)不能满足的情况下)?

“多么频繁”这个问题客观上无法回答。

(我可以请给个例子吗)

偶尔,应用程序可能需要使用ArrayList API中不在List API中的方法。例如,ensureCapacity(int)trimToSize()removeRange(int,int)。(最后一个只会出现在您创建了一个声明该方法为public的ArrayList的子类型的情况下。)

在我看来,编码到类而不是接口是唯一合理的理由。

(理论上可能会在某些平台下的某些情况下略微提高性能……但除非你真正需要最后的0.05%,否则不值得这样做。在我看来,这不是一个合理的理由。)


如果你不知道随机访问是否有效,那么就不能编写高效的代码。

这是一个有道理的观点。然而,Java提供了更好的解决方法,例如:

public  void test(T list) {
    // do stuff
}

如果你用一个没有实现RandomAccess的列表来调用它,你会得到一个编译错误。

你也可以动态地测试……使用instanceof……如果静态类型过于笨拙。你甚至可以编写你的代码来使用不同的算法(动态地),具体取决于列表是否支持随机访问。

请注意,ArrayList不是唯一实现RandomAccess的列表类。其他的包括CopyOnWriteListStackVector

我见过人们对Serializable提出同样的争论(因为List没有实现它)……但上面的方法也解决了这个问题。(在使用运行时类型时,只要有一个元素不可序列化,ArrayList就会失败地序列化。)


最后,我不会说“因为它是好的风格”。这个“理由”既是一个循环论证(“为什么是‘好的风格’?”),也是向一个未明示(并可能不存在!)的更高权威的呼吁(“谁说它是‘好的风格’?”)。

我认为按照接口编程是一种良好的风格,但我不会把它作为理由。最好让你们理解真正的原因,自行得出(我认为)正确的结论。根据不同的上下文,正确的结论可能并不总是相同的。

0
0 Comments

一般情况下,我们会更倾向于使用List而不是ArrayList,因为List可以被转换成LinkedList,而不会影响其他的代码部分。

如果选择使用ArrayList而不是List,那么将很难把ArrayList实现改成LinkedList,因为已经在代码库中使用了ArrayList特定的方法,这也需要进行重构。

您可以在这里了解有关List实现的信息。

您可以先从ArrayList开始,但很快您可能会发现另一种实现是更合适的选择。

0