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

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

我知道,对于(1),List接口的实现可以交换。似乎(1)通常在应用程序中使用,无论是否需要(我自己总是使用它)。

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

此外,情况实际上需要使用(1)而不是(2)的频率是多少(请给我一个例子)(即(2)是不够的..除了编码到接口和最佳实践等)。


当前回答

例如,你可能认为LinkedList是应用程序的最佳选择,但后来又认为ArrayList可能是更好的选择。

Use:

List list = new ArrayList(100); // will be better also to set the initial capacity of a collection 

而不是:

ArrayList list = new ArrayList();

供参考:

(主要用于收集图)

其他回答

我认为使用(2)的人不知道利斯科夫替换原则或依赖反转原则。或者必须使用数组列表。

将HashSet或TreeSet的引用存储在Set类型的变量中被认为是很好的风格。

Set<String> names = new HashSet<String>();

这样,如果您决定使用TreeSet,则只需更改一行。

同样,操作Set的方法应该指定Set类型的参数:

(Set<String> s)

然后,该方法可用于所有set实现。

理论上,我们应该对链表提出同样的建议,即保存 LinkedList在List类型变量中的引用。然而,在Java库中,List接口对于ArrayList和LinkedList类都是通用的。特别是,它有用于随机访问的get和set方法,尽管这些方法对于链表来说效率非常低。

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

这显然是标准库中的一个严重设计错误,我不建议使用 List接口就是因为这个原因。

看看这个错误有多尴尬吧 Collections类的binarySearch方法的源代码。这个方法需要 列表参数,但二分搜索对链表没有意义。然后代码就笨拙了 尝试发现列表是否是链表,然后切换到线性搜索!

Set接口和Map接口设计得很好,您应该使用它们。

我所知道的(2)可以更好的唯一情况是使用GWT,因为它减少了应用程序的占用空间(不是我的想法,但谷歌web工具包团队是这么说的)。但是对于在JVM(1)中运行的常规java来说,可能总是更好。

事实上,有些情况下(2)不仅是首选的,而且是强制性的,我很惊讶,这里没有人提到这一点。

串行化!

如果您有一个可序列化的类,并且希望它包含一个列表,那么您必须将字段声明为具体的可序列化类型,例如ArrayList,因为list接口没有扩展java.io.Serializable

显然,大多数人不需要序列化,忘记了这一点。

一个例子:

public class ExampleData implements java.io.Serializable {

// The following also guarantees that strings is always an ArrayList.
private final ArrayList<String> strings = new ArrayList<>();
(3) Collection myCollection = new ArrayList<?>();

我通常用这个。只有当我需要List方法时,我才会使用List。数组列表也是一样。你总是可以切换到更“窄”的界面,但你不能切换到更“宽”的界面。