多态性:为什么使用“List list = new ArrayList”而不是“ArrayList list = new ArrayList”? [重复]

问题

可能重复:为什么要优先选择Java类的接口?

我应该什么时候使用

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

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


#1 热门回答(218 赞)

你这样做的主要原因是将代码与特定的接口实现分离。当你编写如下代码时:

List list = new ArrayList();

其余代码只知道数据类型为List,这是首选,因为它允许你轻松地在List接口的不同实现之间切换。

例如,假设你正在编写一个相当大的第三方库,并说你决定使用aLinkedList实现库的核心。如果你的图书馆在很大程度上依赖于访问这些列表中的元素,那么最终你会发现你做出了糟糕的设计决策;你会意识到你应该使用anArrayList(它提供O(1)访问时间)而不是aLinkedList(它提供O(n)访问时间)。假设你已经编程到接口,那么进行这样的更改很容易。你只需要更改List的实例,

List list = new LinkedList();

List list = new ArrayList();

并且你知道这将起作用,因为你已编写代码以遵循List接口提供的合同。

另一方面,如果你使用LinkedList list = new LinkedList()实现了库的核心,那么进行此类更改将不会那么容易,因为无法保证你的其余代码不会使用特定于LinkedList类的方法。

总而言之,选择只是设计问题......但这种设计非常重要(特别是在处理大型项目时),因为它允许你在不破坏现有代码的情况下进行特定于实现的更改。


#2 热门回答(63 赞)

这称为编程接口。如果你希望将来转移到List的其他实现,这将非常有用。如果你想在ArrayList中使用某些方法,那么你需要编程到ArrayList a = new ArrayList()的实现。


#3 热门回答(19 赞)

这在暴露公共接口时也很有用。如果你有这样的方法,

public ArrayList getList();

然后你决定改成它,

public LinkedList getList();

任何正在做331111846的人都需要更改他们的代码。另一方面,如果你这样做,

public List getList();

更改实施不会改变API用户的任何内容。