代码通过其接口类型(例如,Set)而不是其实现类型来引用Collection

时间:2014-10-27 11:28:47

标签: java collections

我看到大多数代码总是通过其接口类型(例如,Set)而不是其实现类型来引用Collection。

以下是Oracle's Java Tutorial

提供的原因
  

这是一个强烈推荐的编程实践,因为它给你   仅通过更改构造函数就可以灵活地更改实现。   如果用于存储集合的任何变量或使用的参数   传递它被声明为Collection的实现类型   而不是它的接口类型,所有这些变量和参数必须是   已更改,以便更改其实施类型。

此外,作者提供并不能保证生成的程序能够正常工作。如果程序使用原始 实施类型 中的任何 非标准操作 ,但 不在新的 ,程序将失败。仅通过其界面引用集合会阻止您使用任何非标准操作。

作者谈到的非标准操作是什么?

其次,如何仅通过其界面引用集合会阻止我们使用任何非标准操作?

请在Java代码的帮助下详细说明?

3 个答案:

答案 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)
    ...

这就是为什么即使您只使用标准操作,您的程序也会失败的一个例子。