为什么要将对象分配给接口?

我曾多次听说过在实例化对象时你应该这样做:

“Interface”name = new“Class”();

例如,对于实现List的类链表:

 List name = new LinkedList(); 

LinkedList实现了许多接口,包括queue,deque等。上面的代码和之间有什么区别

 LinkedList name = new LinkedList(); 

要么

 Queue name = new LinkedList(); 

为什么必须两次指定类型; 这似乎是多余的,但oracledocs似乎并未提及它。

LinkedList name = new LinkedList(); 在Java 7中是多余的。它可以重写为LinkedList name = new LinkedList<>();

你想写类似的东西的原因:

 // Java 7 way: List name = new LinkedList<>(); 

如果您改变主意,将为您提供更改数据收集的自由。 您的代码以这种方式更加灵活。 您应该注意的是,您可以使用的方法仅限于左侧类型(在本例中为List )。 这意味着如果您使用层次结构中较高的类型( Object是极端示例),您可能无法获得所需的所有function。

 LinkedList name = new LinkedList<>(); 

将公开LinkedList及其超类中定义的方法。

 Queue name = new LinkedList<>(); 

将公开Queue中定义的方法及其扩展的接口。

您应该将对象定义为一个类/接口,它包含您需要的所有内容(方法,变量等),同时使其尽可能抽象。

例如,这隐藏了实现细节并允许在实现之间更容易地切换。

请注意,由于菱形运算符,您不必在初始化中指定类型。

首先,Interface是一种抽象类型,用于指定类必须实现的内容。 实现接口的任何类都必须通过实现其方法来满足其合同,并且属于该类型。因此,通过实现List接口,LinkList是一种列表。

通过编码到接口而不是具体类,您的代码变得更松散耦合。 这意味着您的代码不是绑定到LinkList而是绑定到List接口,并且可以随时更改为实现列表接口的任何内容。 因此,如果出于某种原因,LinkList不再满足您的要求并且您需要,那么让我们说一个ArrayList,因为它也实现了List接口,您只需更改为:

 List name = new ArrayList(); 

并且所有其他编程逻辑将保持不变,因为两个类具有相同的方法,因为它们实现相同的接口。

这并不像看起来那么简单。 如果您使用:

 List name = new LinkedList(); 

如果你想从链接列表切换到arraylists,那么维护就更少了。

关于冗余, List name = new LinkedList()声明List类型的name并调用LinkedList构造函数。 你可以这样:

 List name = someRandomObject.someRandomHelperMethod(); 

这个辅助方法“刚刚发生”以返回一个列表,因此没有冗余。

使用Java 7,可以跳过明显冗余的通用args:

 List someL = new ArrayList<>(); 

而不是

 List someL = new ArrayList(); 

如果您对接口进行编码,则可以轻松地轻松切换实现。 如果ArrayList比LinkedList更适合您的需求,那么您只能更改一行。 如果您需要LinkedList类(或任何其他子类型)中的特定方法,那么它是完全有效的

 LinkedList name = new LinkedList() 

至于冗余,如果您指的是generics类型声明,那么我建议您查看Guava库。 这些有一些很好的静态导入方法来删除它。 例如, 对于ArrayList ,它将是

 List name = newArrayList() 

代替

 List name = new ArrayList() 

LinkedList也有类似的方法。

在Java 7中还有钻石操作符,但这仍然比Guava的静态导入更冗长。

上面的代码和之间有什么区别

 LinkedList name = new LinkedList(); 

要么

 Queue name = new LinkedList(); 

有几个关键的区别。

使用List接口和使用LinkedList对象之间的区别在于我定义了与实现对象的交互以遵守List接口。 最终,我不关心实现是什么*,只要它表现得像某种List

如果我使用具体的LinkedList对象,那么我不仅要关心类型是什么,而且我可以使用比我应该更多的东西 – 因为它也实现了Queue接口,我可以对它进行类似队列的操作,可能适合也可能不适合。

最终,您的代码应该是SOLID ; 在这里,我们遵循依赖性倒置原则 ,它允许我们依赖于接口而不是具体的实现。 它允许我们根据需要为ArrayList替换LinkedList

*:当然,出于性能原因,您应该关注底层实现。 但是,你可能还不在乎。