我已经多次看过这样的代码:
List<String> list = new ArrayList<String>();
为什么人们采用ArrayList
(和其他类)的父代而不是生成对象的类型?
这会降低性能吗?或者为什么有人这样做?
答案 0 :(得分:37)
当有人写这样的代码时,他/她正试图遵循一个基本的OO设计原则,该原则说 -
编程到接口,而不是具体实现
我在one of my blog posts中解释了这个原则。查看Class Inheritance VS Interface Inheritance
部分。
总结帖子,当您使用父类型的引用来引用子类型的实例时,您将获得很大的灵活性。例如,如果您将来需要更改子类型实现,则可以轻松地执行此操作,而无需更改大量代码。
考虑以下方法 -
public void DoSomeStuff(Super s) {
s.someMethod();
}
并调用此方法 -
DoSomeStuff(new Sub());
现在,如果您需要更改someMethod
内的逻辑,可以通过声明Super
的新子类型,比如说NewSubType
并更改其中的逻辑来轻松完成实现。通过这种方式,您将永远不必触及使用该方法的其他现有代码。您仍然可以通过以下方式使用DoSomeStuff
方法 -
DoSomeStuff(new NewSubType());
如果您将DoSomeStuff
的参数声明为Sub
,则您必须更改其实施 -
DoSomeStuff(NewSubType s) {
s.someMethod();
}
它也可能链接/冒泡到其他几个地方。
就收集示例而言,这可以让您更改变量指向的列表实现,而不会有太多麻烦。您可以轻松使用LinkedList
代替ArrayList
。
答案 1 :(得分:11)
这意味着您可以在任何位置使用实现list
接口的任何内容替换List
的类型,而不是创建只能使用ArrayList
的刚性模型。例如:
private List<String> list;
public SomeConstructor()
{
// At this point, you can make it any type of object you want.
list = new ArrayList<String>();
list = new LinkedList<String>();
list = new AttributeList<String>();
}
这将abstract
使用list
对象的代码,远离细节,例如确切的对象类型list
。它需要知道的是它有add
方法等。这称为Loose Coupling。
答案 2 :(得分:10)
当你写:
List<String> list = new ArrayList<String>();
然后您确定只使用界面 List
的功能。
(ArrayList
实现List
,所以{{ 1}}更灵活)。
使用此功能,您可以在将来将List
更改为其他类型(例如ArrayList
..)。
答案 3 :(得分:5)
要解决问题:
为了获得更大的灵活性,您可以启动界面List
:
因此,如果您不需要所有ArrayList
仅使用List
。
你可以这样写:List<String> = Arrays.asList("aa", "bb","cc")
。
当然,较少的功能可以帮助提高性能。如您所知,如果您想使用多线程应用程序,请改用Vector
,但这会降低您的性能。
从here
开始答案 4 :(得分:4)
因为方法不必知道您使用的列表实现。
方法只需要知道它是一个列表。
仍然可以使用方法。
始终编程到接口,而不是具体实现。 (在本例中为List)
答案 5 :(得分:3)
通常情况下,最好使用Interface类(在本例中为List
),这样如果需求发生变化,以后任何List实现都可以用最小的烦恼代替。
虽然ArrayList
可能支持一些不在List
接口上的方法,但是这个声明清楚地表明那些额外的方法在那种情况下是不相关的。
答案 6 :(得分:2)
List<String> list = new ArrayList<String>();
在集合框架中List
是一个接口,ArrayList
是实现。这样做的主要原因是将代码与接口的特定implementation
分离,如果您希望将来转移到List
的其他实现,这将非常有用。