(1) List<?> myList = new ArrayList<?>();
(2) ArrayList<?> myList = new ArrayList<?>();
我了解使用(1),可以交换List接口的实现。 似乎(1)通常在应用程序中使用,而不需要它(我自己总是使用它)。
我想知道是否有人使用(2)?
另外,这种情况实际上需要多久(并且我可以举个例子),实际上需要使用(1)而不是(2)(即,其中(2)不足以..除了编码接口和最佳实践等之外)。
#1楼
如果代码是列表的“所有者”,则使用(2)。 例如,对于仅局部变量,则为true。 没有理由使用抽象类型List
而不是ArrayList
。 另一个显示所有权的示例:
public class Test {
// This object is the owner of strings, so use the concrete type.
private final ArrayList<String> strings = new ArrayList<>();
// This object uses the argument but doesn't own it, so use abstract type.
public void addStrings(List<String> add) {
strings.addAll(add);
}
// Here we return the list but we do not give ownership away, so use abstract type. This also allows to create optionally an unmodifiable list.
public List<String> getStrings() {
return Collections.unmodifiableList(strings);
}
// Here we create a new list and give ownership to the caller. Use concrete type.
public ArrayList<String> getStringsCopy() {
return new ArrayList<>(strings);
}
}
#2楼
HashSet
或TreeSet
的引用存储在Set类型的变量中被认为是一种很好的样式 。
Set<String> names = new HashSet<String>();
这样,如果您决定改用TreeSet
,则只需更改一行。
另外,对集合进行操作的方法应指定Set类型的参数:
public static void print(Set<String> s)
然后, 该方法可用于所有set实现 。
从理论上讲,我们应该对链接列表提出相同的建议,即将LinkedList引用保存在List类型的变量中。 但是,在Java库中,List接口是ArrayList
和LinkedList
类所共有的。 特别是,它具有用于随机访问的get和set方法,即使这些方法对于链表来说效率很低。
如果您不知道随机访问是否有效, 就无法编写高效的代码 。
在标准库中,这显然是一个严重的设计错误,因此,我不建议使用List接口。
要查看该错误的binarySearch
程度,请查看Collections类的binarySearch
方法的源代码。 该方法采用List参数,但是二进制搜索对于链接列表没有任何意义。 然后,代码笨拙地尝试发现列表是否为链接列表,然后切换到线性搜索!
Set