12

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

“接口”名称=新的“类”();

例如对于实现的类链表List

List<String> name = new LinkedList<String>();

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

LinkedList<String> name = new LinkedList<String>();

或者

Queue<String> name = new LinkedList<String>();

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

4

6 回答 6

10

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

您要编写类似于以下内容的原因:

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

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

于 2013-10-26T21:11:48.133 回答
2
LinkedList<String> name = new LinkedList<>();

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

Queue<String> name = new LinkedList<>();

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

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

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

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

于 2013-10-26T21:11:02.390 回答
2

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

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

List<String> name = new ArrayList<String>();

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

于 2013-10-26T21:41:57.273 回答
1

上面的代码和有什么区别

LinkedList<String> name = new LinkedList<String>();

或者

Queue<String> name = new LinkedList<String>();

有几个关键的区别。

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

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

最终,您的代码应该是SOLID;在这里,我们坚持依赖倒置原则,它允许我们依赖接口而不是具体的实现。它允许我们用我们想要的LinkedList替换ArrayList

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

于 2013-10-26T21:31:31.637 回答
0

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

LinkedList<String> name = new LinkedList<String>()

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

List<String> name = newArrayList()

代替

List<String> name = new ArrayList<String>()

LinkedList 也有类似的方法。

在 Java 7 中也有菱形运算符,但这仍然比从 Guava 的静态导入更冗长。

于 2013-10-26T21:14:00.737 回答
0

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

List<Foo> name = new LinkedList<Foo>();

如果您曾经想从链表切换到数组列表,那么维护就会减少。

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

List<Foo> name = someRandomObject.someRandomHelperMethod();

这个辅助方法“恰好”返回一个列表,所以没有冗余。

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

List<Foo> someL = new ArrayList<>();

List<Foo> someL = new ArrayList<Foo>();
于 2013-10-26T21:10:25.193 回答