4

我不明白之间的区别:

  1. ArrayList<Integer> list = new ArrayList<Integer>();
  2. Collection<Integer> list1 = new ArrayList<Integer>();

ArrayList扩展了实现接口Collection的类,所以类ArrayList实现了Collection接口。也许list1允许我们使用Collection接口中的静态方法?

4

5 回答 5

12

接口没有静态方法 [在 Java 7 中]。list1只允许访问 中的方法Collection,而list允许访问 中的所有方法ArrayList


最好声明一个具有其最不具体的可能类型的变量。因此,例如,如果您更改ArrayListLinkedListHashSet出于任何原因,您不必重构大部分代码(例如,客户端类)。

想象一下你有这样的东西(仅用于说明目的,不可编译):

class CustomerProvider {
    public LinkedList<Customer> getAllCustomersInCity(City city) {
        // retrieve and return all customers for that city
    }
}

然后你决定实现它返回一个HashSet. 也许有一些客户端类依赖于您返回的事实LinkedList,并调用HashSet没有的方法(例如LinkedList.getFirst())。

这就是为什么你最好这样做:

class CustomerProvider {
    public Collection<Customer> getAllCustomersInCity(City city) {
        // retrieve and return all customers for that city
    }
}
于 2013-01-04T19:08:47.707 回答
2

我们在这里处理的是interfaceimplementation之间的区别。

接口是一组方法,与这些方法的实现方式无关。当我们将一个对象实例化为具有实际上是的类型时,interface我们的意思是,它是一个实现了其中所有方法的对象interface......但不提供访问其中任何方法的权限class实际上提供了这些实现。

当您实例化一个具有实现类型的对象时class,您就可以访问该对象的所有相关方法class。由于这class是实现一个interface,您可以访问接口中指定的方法,以及实现类提供的任何附加功能。

你为什么想做这个?好吧,通过将对象的类型限制为interface,您可以切换到新的实现,而不必担心更改其余代码。这使它变得更加灵活。

于 2013-01-04T19:13:26.033 回答
2

Collection正如其他人所说,不同之处在于,当您将其指定为变量类型时,您仅限于接口定义的方法。但这并不能回答您为什么要这样做的问题。

原因是数据类型的选择为使用代码的人提供了信息。特别是当用作函数的参数或返回类型时(外部程序员可能无法访问内部)。

根据具体情况,以下是不同类型选择可能会告诉您的信息:

  • Collection- 一组对象,没有进一步的保证。这个对象的消费者可以迭代集合(不保证迭代顺序),并且可以知道它的大小,但不能做任何其他事情。
  • List- 一组具有特定顺序的对象。当您遍历这些对象时,您将始终以相同的顺序获取它们。您还可以通过索引从集合中检索特定项目,但您不能对此类检索的性能做出任何假设。
  • ArrayList- 一组具有特定顺序的对象,可以通过索引在恒定时间内访问。

尽管您没有询问它们,但这里有一些其他集合类:

  • Set保证每个equals()方法不包含重复项的一组对象。不保证这些对象的迭代顺序。
  • SortedSet一组不包含重复项的对象,并且始终以特定顺序迭代(尽管集合不保证该特定顺序)。
  • TreeSet一组没有重复的有序对象,显示O(logN)插入和检索时间。
  • HashSet一组没有重复的对象,它们没有固有的顺序,但提供(摊销的)恒定时间访问。
于 2013-01-04T19:57:50.293 回答
1

唯一的区别是您通过 Collection 接口提供对 list1 的访问,而您通过 ArrayList 接口提供对 list2 的访问。有时,通过受限接口提供访问很有用,因为它促进了封装并减少了对实现细节的依赖。

于 2013-01-04T19:09:09.783 回答
0

当您对“list1”执行操作时,您将只能从 Collection 接口访问方法(get、size 等)。通过将“list”声明为 ArrayList,您可以访问仅在 ArrayList 类中定义的其他方法(例如,ensureCapacity 和 trimToSize。

将变量声明为您需要的最不具体的类通常是最佳实践。因此,如果您只需要 Collection 中的方法,请使用它。通常在这种情况下,这意味着使用 List,它可以让您知道它是有序的并且可以处理重复项。

使用最不具体的类/接口允许您在以后自由更改实现。例如,如果您稍后了解到 LinkedList 将是一个更好的实现,如果您将变量定义为 List,您可以在不破坏所有代码的情况下更改它。

于 2013-01-04T19:10:59.823 回答