多态:为什么使用“List list = new ArrayList”而不是“ArrayList list = new ArrayList”?

可能重复:
为什么要selectJava类的接口呢?

我应该什么时候使用

List<Object> list = new ArrayList<Object>(); 

ArrayListListinheritance,所以如果ArrayList中的某些特性不在List ,那么我将失去ArrayList一些特性,对吧? 编译器在尝试访问这些方法时会注意到一个错误?

你这样做的主要原因是将你的代码从接口的特定实现中分离出来。 当你写这样的代码:

 List list = new ArrayList(); 

剩下的代码只知道数据是Listtypes的,这是最好的,因为它允许你轻松地在List接口的不同实现之间切换。

例如,假设你正在编写一个相当大的第三方库,并且说你决定用一个LinkedList来实现你的库的核心。 如果你的图书馆很大程度上依赖于访问这些列表中的元素,那么最终你会发现你做出了糟糕的devise决定; 你会意识到你应该使用一个ArrayList (它给出了O(1)访问时间),而不是一个LinkedList (它给出O(n)访问时间)。 假设你已经编程到一个接口,做这样的改变很容易。 你可以简单的改变List的实例,

 List list = new LinkedList(); 

 List list = new ArrayList(); 

而且你知道这会起作用,因为你已经编写了你的​​代码来遵循List接口提供的合同。

另一方面,如果你已经使用LinkedList list = new LinkedList()实现了你的库的核心,那么做这样的改变就不那么容易,因为不能保证你的代码的其他部分没有被使用特定于LinkedList类的方法。

总而言之,select只是一个devise问题…但是这种devise是非常重要的(特别是在处理大型项目时),因为它可以使您在不破坏现有代码的情况下进行特定于实现的更改。

这被称为编程接口。 如果您希望将来转移到List的其他实现,这将会有所帮助。 如果你想在ArrayList一些方法,那么你需要ArrayList a = new ArrayList()

暴露公共界面时这也很有帮助。 如果你有这样的方法,

 public ArrayList getList(); 

然后你决定改变它,

 public LinkedList getList(); 

任何正在做ArrayList list = yourClass.getList()都需要改变他们的代码。 另一方面,如果你这样做,

 public List getList(); 

更改实现不会为您的API的用户更改任何内容。

我认为@ tsatiz的答案大部分是正确的(编程到接口而不是实现)。 但是, 通过编程接口,您将不会失去任何function 。 让我解释。

如果将variables声明为List<type> list = new ArrayList<type> ,则实际上不会丢失ArrayList的任何function。 所有你需要做的就是将你的list成一个ArrayList 。 这是一个例子:

 List<String> list = new ArrayList<String>(); ((ArrayList<String>) list).ensureCapacity(19); 

最终我认为tsatiz是正确的,因为一旦你投到一个ArrayList你不再编码到一个接口。 但是,最初编写一个接口还是一个很好的做法,如果必须的话,如果以后有必要的话,还可以编写一个实现。

希望有所帮助!

这使您可以写下如下内容:

 void doSomething() { List<String>list = new ArrayList<String>(); //do something } 

稍后,您可能需要将其更改为:

 void doSomething() { List<String>list = new LinkedList<String>(); //do something } 

而不必更改方法的其余部分。

但是,如果您想要使用CopyOnWriteArrayList ,例如,您需要声明它,而不是作为List 来使用其额外的方法 (例如addIfAbsent):

 void doSomething() { CopyOnWriteArrayList<String>list = new CopyOnWriteArrayList<String>(); //do something, for example: list.addIfAbsent("abc"); } 

只要我不想增加问题的复杂性,我就使用这种构造。 这只是一个列表,不需要说明它是什么样的列表,因为这个问题并不重要。 我经常使用Collection来获取我的大部分解决scheme,因为在大多数情况下,对于其他软件来说,真正重要的是它所包含的内容,而且我不想将新对象添加到Collection中。

而且,当你认为你可能想要改变你正在使用的列表的实现时,你使用这种构造。 假设您正在使用ArrayList构造,并且您的问题不是线程安全的。 现在,您希望使线程安全,并且对于您的部分解决scheme,例如,您将更改为使用Vector。 至于那个列表的其他用途,如果它是一个AraryList或者一个Vector,只是一个List,那么这个列表就不会有问题,不需要重新修改。

我想你的问题的核心是为什么program to an interface, not to an implementation

简单地说,因为一个接口给了你更多的抽象,并且使得代码更加灵活和易于修改,因为你可以使用同一接口的不同实现(在这种情况下,你可能想要将你的List实现改为linkedList而不是ArrayList)而不改变其客户。

一般来说,你想对接口进行编程。 这使您可以随时交换实施。 这是非常有用的,特别是当你通过一个你不知道的实现。

但是,在某些情况下,您更愿意使用具体的实现。 例如,当在GWT序列化。