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