(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)是不够的..除了编码到接口和最佳实践等)。
当前回答
事实上,有些情况下(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<>();
其他回答
我认为使用(2)的人不知道利斯科夫替换原则或依赖反转原则。或者必须使用数组列表。
列表接口有几个不同的类——ArrayList和LinkedList。LinkedList用于创建索引集合,ArrayList用于创建排序列表。你可以在你的参数中使用它,但是你可以允许其他使用你的代码,库等的开发人员使用不同类型的列表,而不仅仅是你在这个方法中使用的
ArrayList<Object> myMethod (ArrayList<Object> input) {
// body
}
你只能在ArrayList中使用它,而不是LinkedList,但是你可以允许在其他地方使用它的方法,这只是你的选择,所以使用接口可以允许它:
List<Object> myMethod (List<Object> input) {
// body
}
在这个方法参数中,你可以使用任何你想使用的List类:
List<Object> list = new ArrayList<Object> ();
list.add ("string");
myMethod (list);
结论:
尽可能在任何地方使用接口,不要限制您或其他人使用他们想要使用的不同方法。
将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接口设计得很好,您应该使用它们。
我会说1是首选,除非
你依赖于ArrayList中可选行为*的实现,在这种情况下显式使用ArrayList更清楚 你将在一个需要ArrayList的方法调用中使用ArrayList,可能用于可选的行为或性能特征
我的猜测是,在99%的情况下,您可以使用List,这是首选。
为实例removeAll,或add(null)
事实上,有些情况下(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<>();