我们想说我想为数字创建一个ArrayList
。我学习它的方式是这样的:
private static List<Integer> numbers = new ArrayList<Integer>();
但IntelliJ IDEA希望将其更正为
private static List<Integer> numbers = new ArrayList<>();
然后我发现这也有效:
private static List<Integer> numbers = new ArrayList();
现在我很困惑,最好的方法是什么?那是什么区别。同样的问题适用于HashMap
。
答案 0 :(得分:7)
最好的方法是:
private static List<Integer> numbers = new ArrayList<>(); // Java 7
private static List<Integer> numbers = new ArrayList<Integer>(); // Java 6
让我们看看其他例子:
private static ArrayList<Integer> numbers = new ArrayList<Integer>();
使用特定的类作为类型,除非您需要访问特定于ArrayList的方法(我不知道),否则不建议使用它。
private static ArrayList<Integer> numbers = new ArrayList();
类型不安全,您的IDE会在此行上发出警告。
答案 1 :(得分:3)
您应该使用左侧的界面:
private static List<Integer> numbers = new ArrayList<>();
除非您确实需要该数据结构的任何特定方法。
IntelliJ IDEA建议您构建,因为您使用的是JDK 1.7.x(或更高级),并且无需再次指定类型,因为编译器可以infer the type arguments from the context(再次来自Java 7和/或更高版本。)
答案 2 :(得分:2)
所有给出的示例将编译为相同的字节码,而不会影响后续的类型检查。使用这一个或另一个的原因是避免恼人的警告。
new ArrayList();
是 pre-generics 方式。编译器会警告您,因为您不关心泛型(并且可能使用ArrayList
以外的元素分配Integer
。new ArrayList<Integer>();
是泛型方式,但之前编译器足够智能推断本身的元素类型。因此它会警告你,因为它比必要的更冗长。new ArrayList<>();
是目前首选的方式(感谢Java 7中引入的Type Inference(see related SO question))。除非你必须处理旧的编译器,否则就去做吧。也许一个有趣的问题是为什么new ArrayList<>();
最好(类型推断),但new ArrayList();
不是。
答案 3 :(得分:1)
第一个例子是正确的,你提供了所需的一切。但它也意味着你重复参数类型的定义。
然后,在Java 1.7(或者1.8,不太确定)中,他们引入了缩短版本 - 因此,如果您定义ArrayList<Integer> numbers
,则无需为{{ArrayList
定义重复Integer
应该创建1}},然后在那里保留<>
。这有时称为菱形表示法,并指示编译器使用与字段定义相同的数据类型。因此,它的行为与第一个示例完全相同,但无需复制有关数据类型的信息。
当您创建没有指定数据类型的ArrayList
时,您遇到的最后一种情况会有所不同。这可能有些危险,因为它允许您编写以下代码:
List listAnything = new ArrayList();
listAnything.add("string");
listAnything.add(42);
listAnything.add(false);
List<Integer> listInteger = listAnything;
上面列出的代码编译完全正常,但有一些关于未经检查的转换和使用原始类型的警告。您不再保证listInteger
仅包含整数。
另外,在这里警告 - 你应该在代码中尽可能多地依赖抽象。我的意思是使用接口或抽象类而不是具体的类来定义字段。这样的代码在阅读和维护方面要好得多:
ArrayList<Integer> list = new ArrayList<>(); // this is not wrong...
List<Integer> list = new ArrayList<>(); // ...but this is better