18

这是一个真正的初学者问题(我仍在学习 Java 基础知识)。

我可以(某种程度上)理解为什么方法会返回 List<String> 而不是 ArrayList<String>,或者为什么它们会接受 List 参数而不是 ArrayList。如果它对方法没有影响(即,如果不需要来自 ArrayList 的特殊方法),这将使该方法更灵活,并且更易于调用者使用。其他集合类型也是如此,例如 Set 或 Map。

我不明白的是:创建这样的局部变量似乎是一种常见的做法:

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

虽然这种形式不太常见:

ArrayList<String> list = new ArrayList<String>();

这里有什么好处?

我所看到的只是一个小缺点:必须为 java.util.List 添加一个单独的“导入”行。从技术上讲,可以使用“import java.util.*”,但我也不经常看到这种情况,可能是因为某些 IDE 自动添加了“import”行。

4

7 回答 7

21

当你阅读

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

您会认为您所关心的只是成为一个List<String>,并且您对实际实施的重视程度较低。此外,您将自己限制为由List<String>而不是特定实现声明的成员。你不在乎你的数据是存储在线性数组还是一些花哨的数据结构中,只要它看起来像List<String>.

另一方面,阅读第二行可以让您了解代码关心的变量是ArrayList<String>. 通过写这篇文章,你暗示(对未来的读者)你不应该盲目地改变实际的对象类型,因为其余的代码依赖于它实际上是一个ArrayList<String>.

于 2009-09-27T20:57:07.257 回答
7

使用该接口可以快速更改 List/Map/Set/etc 的底层实现。

这不是关于节省击键,而是关于快速改变实现。理想情况下,您不应该公开实现的底层特定方法,而只使用所需的接口。

于 2009-09-27T21:00:13.290 回答
2

我建议从另一端考虑这个问题。通常你想要一个 List 或一个 Set 或任何其他 Collection 类型——你真的不关心你的代码是如何实现的。因此,您的代码只适用于 List 并做它需要做的任何事情(也被称为“始终编码到接口”)。

当您创建列表时,您需要确定您想要的实际实现。对于大多数用途,ArrayList 已经“足够好”,但您的代码真的不在乎。通过坚持使用界面,您可以将其传达给未来的读者。

例如,我习惯在我的 main 方法中使用调试代码,它将系统属性转储到 System.out - 通常对它们进行排序要好得多。最简单的方法是简单地让“Map map = new TreeMap(properties);” 然后遍历它们,因为 TreeMap 返回排序的键。

当您了解更多有关 Java 的知识时,您还将看到接口在测试和模拟方面非常有帮助,因为您可以创建具有在运行时指定的行为符合给定接口的对象。可以在http://www.exampledepot.com/egs/java.lang.reflect/ProxyClass.html看到一个高级(但简单)的示例

于 2009-09-27T21:52:03.540 回答
1

如果稍后您想更改列表的实现并使用例如 LinkedList(也许是为了更好的性能),您不必更改整个代码(如果它的库还有 API)。如果订单无关紧要,您应该返回 Collection 以便稍后您可以轻松地将其更改为 Set 如果您需要对项目进行排序。

于 2009-09-27T20:54:07.413 回答
1

我能想到的最好的解释(因为我不像其他语言那样频繁地用​​ Java 编程)是它可以更容易地更改“后端”列表类型,同时保持相同的代码/接口,其他一切都是靠。如果您首先将其声明为更具体的类型,然后再决定您想要一种不同的类型……如果发生使用 ArrayList 特定方法的事情,那就是额外的工作。

当然,如果您确实需要特定于 ArrayList 的行为,则可以使用特定的变量类型。

于 2009-09-27T20:54:34.870 回答
0

关键是确定您想要/需要的行为,然后使用提供该行为的接口。这是您的变量的类型。然后,使用满足您其他需求的实现 - 效率等。这就是您使用“新”创建的内容。这种二元性是OOD背后的主要思想之一。当您处理局部变量时,这个问题并不是特别重要,但始终遵循良好的编码实践很少会造成伤害。

于 2014-07-25T16:20:52.673 回答
-2

基本上这来自必须运行大型项目的人,可能还有其他原因 - 你一直听到它。为什么,我其实不知道。如果您需要数组列表、哈希映射或哈希集或其他任何东西,我认为通过转换为接口来消除方法没有意义。

举个例子,最近我学习了如何使用和实现HashSet作为一种基本的数据结构。假设,无论出于何种原因,我去一个团队工作。难道那个人不需要知道数据是用散列方法键入的,而不是按某种基础排序的吗?Twisol 指出的后端方法在 C/C++ 中工作,您可以在其中公开标头并出售库,如果有人知道如何在 Java 中做到这一点,我想他们会使用 JNI - 在这一点上对我来说似乎更简单使用 C/C++,您可以在其中公开标头并使用已建立的工具构建库。

当您可以找到可以在扩展目录中安装 jar 文件的人时,在我看来,该实体可能只是几步之遥 - 我在扩展目录中删除了几个加密库,这很方便,但我真的很喜欢看清楚,简明的基础阐明。我想他们一直都在这样做。

在这一点上,这听起来像是经典的混淆,但要注意:在问题产生后果之前,您需要进行一些编码。

于 2009-09-27T23:32:14.450 回答