声明 ArrayList 或集合实现的最佳实践 类

Best practice to declare ArrayList or collection implementation classes

任何人都可以解释以下 ArrayList 声明存储 String 的区别是什么。

List type1 = new ArrayList();
List type2 = new ArrayList<String>();
List<String> type3 = new ArrayList<String>();
ArrayList<String> type4 = new ArrayList<String>();
List<String> type5 = null;
ArrayList<String> type6 = null;

以上哪项声明是声明 ArrayList 字符串的最佳实践,为什么?

  • List type1 = new ArrayList();
  • List type2 = new ArrayList<String>();

    你有 raw type ArrayListList,你不应该使用它们(虽然它是合法代码):

    ... The term "unchecked" means that the compiler does not have enough type information to perform all type checks necessary to ensure type safety

  • List<String> type3 = new ArrayList<String>();

    这个是安全的,因为 Java 7 它可以使用菱形运算符并重写为:

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

    这是最好的,因为它是 接口编程,这意味着您可以将 type3 更改为实现 List 的任何其他 class .

  • ArrayList<String> type4 = new ArrayList<String>();

    这是一个特定的对象,您永远不能将 type4 的类型更改为其他类型而不是 ArrayList

最后两个不能与其余的进行比较,你只是给它们一个默认值,有时你被迫,有时你可以跳过这个初始化。

List<String> type3 = new ArrayList<String>();List<String> type5 = null;

最好不要使用 ListArrayList 等原始类型,声明接口类型的变量比声明实现类型的变量更灵活。

关于是否要将变量初始化为null并稍后实例化List(或者将returns一个List实例的方法的结果赋值给变量) , 或者在你声明它的时候实例化它,我认为这两个选项同样有效。

type1type2Raw Types,应该避免。

type3type4 很好(但不是 IMO 最好的,我会回到那个) - 我更喜欢 type3 而不是 type4 因为它使用接口类型(您应该针对接口进行编程)。例如,您可以使用 Arrays.asList("a","b")type3.

type5type6 类似于 type3type4 但我建议您避免初始化为 null.

最后,Java7+我推荐钻石算子。例如,

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

一般来说,将左侧 最不具体 的类型保留在您执行功能所需的类型中是一种很好的做法。但是,您应该始终参数化可参数化类型并避免使用原始类型。所以你应该使用:

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

请注意,从 Java 7 开始,您还可以省略右侧的类型:

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

稍后,如果您想改用 LinkedList,只需更新创建列表的代码行,而不必更改对它的所有引用。

  • 1 和 2 是原始类型声明。您可以将任何您喜欢的对象类型添加到此列表中,但您无法在编译时保证类型安全。

    以这种方式声明列表 is generally frowned upon,因为不小心将不应该的对象放入列表中可能是一个非常简单的错误。这里真正需要注意的是,这个错误在 运行时 之前不会出现,而使用类型参数会在 编译时 出现这个错误, 这更容易处理。

  • 3 是声明列表(或任何类型的集合)的首选方法,因为您是 bound to the interface 而不是具体实现。它还包括类型边界,保证编译时类型安全。

  • 4 是对具体类型 ArrayList 的声明。如果你需要具体类型,那么这没问题,但你这样做的情况非常少。

  • 5和6分别是3和4的重复;不同之处在于它们都被初始化为空。

前两个使用原始类型。这样做意味着您的列表根本不是类型安全的。即使您的意图是拥有一个字符串列表,编译器也会让您在其中存储整数。编译器会发出警告,您不应忽略。

第三个是对的。它告诉编译器你的意图是使用一个字符串List,你选择的具体实现是ArrayList。如果您稍后改变主意并想使用 LinkedList,则这行代码是您唯一需要更改的代码。

第四个告诉编译器你的程序不仅仅需要一个列表。它需要这个 List 是一个 ArrayList。如果您的代码确实需要调用特定于 ArrayList 且不存在于 List 接口中的方法,则可以这样做。但在99.9%的情况下,情况并非如此,你应该更喜欢第三种。

最后两个声明一个变量并将其初始化为空,而不是创建一个列表。那是一种设计气味。在使用该列表之前,您必须在所有地方确保它不为空。立即使用有效列表对其进行初始化要安全得多。