我多次听说过在实例化对象时应该这样做:
“Interface”name = new“Class”();
例如,对于实现List
的类链表:
List<String> name = new LinkedList<String>();
LinkedList
实现了许多接口,包括queue,deque等。上面代码和
LinkedList<String> name = new LinkedList<String>();
或
Queue<String> name = new LinkedList<String>();
为什么必须两次指定类型;这似乎是多余的,但oracledocs似乎并未提及它。
答案 0 :(得分:7)
LinkedList<String> name = new LinkedList<String>();
在Java 7中是多余的。它可以重写为LinkedList<String> name = new LinkedList<>();
。
你想写类似的东西:
// Java 7 way:
List<String> name = new LinkedList<>();
如果您改变主意,是为您提供以后更改数据收集的自由。您的代码以这种方式更加灵活。您应该注意的是,您可以使用的方法仅限于左侧类型(在这种情况下为List
)。这意味着如果您使用层次结构中较高的类型(Object
是极端示例),则可能无法获得所需的所有功能。
答案 1 :(得分:2)
LinkedList<String> name = new LinkedList<>();
将公开LinkedList
及其超类中定义的方法。
Queue<String> name = new LinkedList<>();
将公开Queue
中定义的方法及其扩展的接口。
您应该将对象定义为一个类/接口,它包含您需要的所有内容(方法,变量等),同时使其尽可能抽象。
这隐藏了实现细节,并允许在实现之间更容易地切换,例如。
请注意,由于钻石运算符,您不必在初始化中指定类型。
答案 2 :(得分:1)
首先,Interface是一种抽象类型,用于指定类必须实现的内容。实现接口的任何类必须通过实现其方法来满足其合同并且属于该类型。因此,通过实现List接口,LinkList是一种列表。
通过编码到接口而不是具体类,您的代码变得更松散耦合。这意味着您的代码不是绑定到LinkList而是绑定到List接口,并且可以随时更改为实现列表接口的任何内容。因此,如果由于某种原因,LinkList不再满足您的需求而需要,请说一个ArrayList,因为它也实现了List接口,您只需更改为:
List<String> name = new ArrayList<String>();
所有其他编程逻辑都保持不变,因为两个类都有相同的方法,因为它们实现了相同的接口。
答案 3 :(得分:0)
这并不像看起来那么简单。如果您使用:
List<Foo> name = new LinkedList<Foo>();
如果你想从链接列表切换到arraylists,那么维护就更少了。
关于冗余,List name = new LinkedList()
声明类型name
的{{1}}并调用List
构造函数。你可以这样:
LinkedList
这个辅助方法“刚刚发生”以返回一个列表,因此没有冗余。
使用Java 7,可以跳过明显冗余的通用args:
List<Foo> name = someRandomObject.someRandomHelperMethod();
而不是
List<Foo> someL = new ArrayList<>();
答案 4 :(得分:0)
如果您对接口进行编码,则可以轻松地轻松切换实现。如果ArrayList比LinkedList更适合您的需求,那么您只能更改一行。如果您需要LinkedList类(或任何其他子类型)中的特定方法,则完全有效
LinkedList<String> name = new LinkedList<String>()
至于冗余,如果您指的是泛型类型声明,那么我建议您查看Guava库。这些有一些很好的静态导入方法来删除它。例如,对于an ArrayList,它将是
List<String> name = newArrayList()
而不是
List<String> name = new ArrayList<String>()
LinkedList也有类似的方法。
在Java 7中还有diamond个运算符,但这仍然比来自Guava的静态导入更加冗长。
答案 5 :(得分:0)
上述代码和
之间有什么区别LinkedList<String> name = new LinkedList<String>();
或
Queue<String> name = new LinkedList<String>();
有一些关键的区别。
使用List
接口和使用LinkedList
对象之间的区别在于我定义了与实现对象的交互以遵守List
接口。最终,我不会关心实现是什么*,只要它表现得像某种List
。
如果我使用具体的LinkedList
对象,那么我不仅要关心类型是什么,而且我可以使用比我应该更多的东西 - 因为它实现了{ {1}}接口,我可以对它进行类似队列的操作,这可能适合也可能不适合。
最终,您的代码应为SOLID;在这里,我们遵循dependency inversion principle,它允许我们依赖于接口而不是具体实现。它允许我们根据需要将Queue
替换为LinkedList
。
*:当然,出于性能原因,您应该关心底层实现是什么。但是,您可能不在乎尚未。