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

时间:2015-04-19 07:10:05

标签: java arraylist collections

任何人都可以解释以下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字符串的最佳做法以及为什么?

6 个答案:

答案 0 :(得分:7)

前两个使用原始类型。这样做意味着您的列表根本不是类型安全的。编译器将允许您将整数存储在内部,即使您的目的是要有一个字符串列表。编译器会发出警告,你不应该忽略它。

第三个是正确的。它告诉编译器您的意图是使用字符串List,并且您选择的特定实现是ArrayList。如果您稍后改变主意并希望使用LinkedList,则此行代码是您需要更改的唯一代码。

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

最后两个声明了一个变量并将其初始化为null而不是创建一个列表。这是一种设计气味。在使用列表之前,您必须确保无处不在。使用有效列表立即初始化它会更安全。

答案 1 :(得分:6)

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

    您有raw type ArrayListList,您不应该使用它们(尽管它是合法代码):

      

    ......术语&#34;未经检查&#34;表示编译器没有足够的类型信息来执行确保类型安全所需的所有类型检查

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

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

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

    它是程序到接口以来最好的,这意味着您可以将type3更改为实现List的任何其他类。

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

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

最后两个无法与其他两个进行比较,您只是简单地给它们一个默认值,有时您会被迫,有时您可以跳过此初始化。

答案 2 :(得分:2)

type1type2Raw Types,应该避免使用。

type3type4很好(但不是IMO最好的,我会回到那里) - 我希望type3type4,因为它使用了接口类型(您应该编程到接口)。例如,您可以使用Arrays.asList("a","b") type3

type5type6type3type4类似,但我建议您避免初始化为null

最后,使用Java 7+,我会推荐钻石操作符。例如,

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

答案 3 :(得分:2)

通常,最好将左侧保持为执行功能所需的最不具体的类型。但是,您应始终参数化可参数化类型并避免原始类型。所以你应该使用:

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

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

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

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

答案 4 :(得分:2)

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

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

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

  • 4是具体类型ArrayList的声明。如果你需要具体的类型,那么这是可以的,但你可以做的事情很少。

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

答案 5 :(得分:1)

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

最好不要使用ListArrayList之类的原始类型,并且更灵活地声明接口类型的变量而不是实现类型。

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