我不明白之间的区别:
ArrayList<Integer> list = new ArrayList<Integer>();
Collection<Integer> list1 = new ArrayList<Integer>();
类ArrayList
扩展了实现接口Collection
的类,所以类ArrayList
实现了Collection
接口。也许list1
允许我们使用Collection
接口中的静态方法?
我不明白之间的区别:
ArrayList<Integer> list = new ArrayList<Integer>();
Collection<Integer> list1 = new ArrayList<Integer>();
类ArrayList
扩展了实现接口Collection
的类,所以类ArrayList
实现了Collection
接口。也许list1
允许我们使用Collection
接口中的静态方法?
接口没有静态方法 [在 Java 7 中]。list1
只允许访问 中的方法Collection
,而list
允许访问 中的所有方法ArrayList
。
最好声明一个具有其最不具体的可能类型的变量。因此,例如,如果您更改ArrayList
为LinkedList
或HashSet
出于任何原因,您不必重构大部分代码(例如,客户端类)。
想象一下你有这样的东西(仅用于说明目的,不可编译):
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
}
}
我们在这里处理的是interface和implementation之间的区别。
接口是一组方法,与这些方法的实现方式无关。当我们将一个对象实例化为具有实际上是的类型时,interface
我们的意思是,它是一个实现了其中所有方法的对象interface
......但不提供访问其中任何方法的权限class
实际上提供了这些实现。
当您实例化一个具有实现类型的对象时class
,您就可以访问该对象的所有相关方法class
。由于这class
是实现一个interface
,您可以访问接口中指定的方法,以及实现类提供的任何附加功能。
你为什么想做这个?好吧,通过将对象的类型限制为interface
,您可以切换到新的实现,而不必担心更改其余代码。这使它变得更加灵活。
Collection
正如其他人所说,不同之处在于,当您将其指定为变量类型时,您仅限于接口定义的方法。但这并不能回答您为什么要这样做的问题。
原因是数据类型的选择为使用代码的人提供了信息。特别是当用作函数的参数或返回类型时(外部程序员可能无法访问内部)。
根据具体情况,以下是不同类型选择可能会告诉您的信息:
Collection
- 一组对象,没有进一步的保证。这个对象的消费者可以迭代集合(不保证迭代顺序),并且可以知道它的大小,但不能做任何其他事情。List
- 一组具有特定顺序的对象。当您遍历这些对象时,您将始终以相同的顺序获取它们。您还可以通过索引从集合中检索特定项目,但您不能对此类检索的性能做出任何假设。ArrayList
- 一组具有特定顺序的对象,可以通过索引在恒定时间内访问。尽管您没有询问它们,但这里有一些其他集合类:
Set
保证每个equals()
方法不包含重复项的一组对象。不保证这些对象的迭代顺序。SortedSet
一组不包含重复项的对象,并且始终以特定顺序迭代(尽管集合不保证该特定顺序)。TreeSet
一组没有重复的有序对象,显示O(logN)
插入和检索时间。HashSet
一组没有重复的对象,它们没有固有的顺序,但提供(摊销的)恒定时间访问。唯一的区别是您通过 Collection 接口提供对 list1 的访问,而您通过 ArrayList 接口提供对 list2 的访问。有时,通过受限接口提供访问很有用,因为它促进了封装并减少了对实现细节的依赖。
当您对“list1”执行操作时,您将只能从 Collection 接口访问方法(get、size 等)。通过将“list”声明为 ArrayList,您可以访问仅在 ArrayList 类中定义的其他方法(例如,ensureCapacity 和 trimToSize。
将变量声明为您需要的最不具体的类通常是最佳实践。因此,如果您只需要 Collection 中的方法,请使用它。通常在这种情况下,这意味着使用 List,它可以让您知道它是有序的并且可以处理重复项。
使用最不具体的类/接口允许您在以后自由更改实现。例如,如果您稍后了解到 LinkedList 将是一个更好的实现,如果您将变量定义为 List,您可以在不破坏所有代码的情况下更改它。