我看到大多数代码总是通过其接口类型(例如,Set)而不是其实现类型来引用Collection。
提供的原因这是一个强烈推荐的编程实践,因为它给你 仅通过更改构造函数就可以灵活地更改实现。 如果用于存储集合的任何变量或使用的参数 传递它被声明为Collection的实现类型 而不是它的接口类型,所有这些变量和参数必须是 已更改,以便更改其实施类型。
此外,作者提供并不能保证生成的程序能够正常工作。如果程序使用原始 实施类型 中的任何 非标准操作 ,但 不在新的 ,程序将失败。仅通过其界面引用集合会阻止您使用任何非标准操作。
作者谈到的非标准操作是什么?
其次,如何仅通过其界面引用集合会阻止我们使用任何非标准操作?
请在Java代码的帮助下详细说明?
答案 0 :(得分:5)
这方面的一个示例是LinkedList
,其中包含getFirst()
和getLast()
方法。使用它们似乎很方便,但如果实现更改为ArrayList
,它们就会消失。
答案 1 :(得分:1)
使用interface for和instance初始化有很多好处。
List list = new Arraylist();
现在你有了list对象,以后可以用于任何实现List接口的类。
但是一旦你ArrayList arraylist = new ArrayList()
,你就会失去这样的机会。
答案 2 :(得分:0)
即使在使用界面时,您仍需要考虑一个陷阱。
请考虑以下代码:
public void sampleMethod(List<String> list) {
list.add("baz");
System.out.println(list);
}
我们仅使用界面定义的标准操作,但如果您检查documentation,您会注意到add()
操作是可选的。
因此,如果您执行以下代码
public void test() {
List<String> sampleList = new ArrayList<>();
sampleList.add("foo");
try {
sampleMethod(sampleList);
}catch (Exception e) {
e.printStackTrace();
}
try {
sampleMethod(Collections.unmodifiableList(sampleList));
}catch (Exception e) {
e.printStackTrace();
}
try {
sampleMethod(Collections.singletonList("bar"));
}catch (Exception e) {
e.printStackTrace();
}
}
你会得到:
[foo, baz]
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.add(Collections.java:1075)
...
java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
...
这就是为什么即使您只使用标准操作,您的程序也会失败的一个例子。