在Java中初始化Generic类的实例时,在语句的两边指定Type是否有任何好处?
或者换句话说,这两个有效陈述之间的区别是什么:
ArrayList<String> test = new ArrayList<String>();
和
ArrayList<String> test = new ArrayList();
(似乎第二个陈述不等同于:
ArrayList<String> test = new ArrayList<Object>();
作为无效的第三个语句并导致incompatible types
编译错误。)
答案 0 :(得分:14)
第二个语句与第一个语句或多或少等同,但仅仅因为泛型在运行时被删除。你会得到一个“未经检查的转换”警告,这就是我不喜欢的原因。
更好的方法是使用这样的静态泛型方法:
public static <T> List<T> newList() {
return new ArrayList<T>();
}
然后再做
List<String> test = newList();
Google Collections就是这样做的。
(并且您应该几乎总是将您的列表声明为List
,而不是ArrayList
。稍后可以轻松切换实施。)
编辑:运动员在评论中询问两个声明之间的确切区别,以及为什么我说它们“或多或少相当”。由于type erasure,它们之间的唯一区别是警告。这是一小段代码比较它们:
import java.util.*;
class GenericDeclarationTest {
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
list1.add("");
String s1 = list1.get(0);
List<String> list2 = new ArrayList();
list2.add("");
String s2 = list2.get(0);
}
}
这是生成的字节码(由javap -c GenericDeclarationTest
打印):
Compiled from "GenericDeclarationTest.java"
class GenericDeclarationTest extends java.lang.Object{
GenericDeclarationTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2; //class java/util/ArrayList
3: dup
4: invokespecial #3; //Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: ldc #4; //String
11: invokeinterface #5, 2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
16: pop
17: aload_1
18: iconst_0
19: invokeinterface #6, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
24: checkcast #7; //class java/lang/String
27: astore_2
28: new #2; //class java/util/ArrayList
31: dup
32: invokespecial #3; //Method java/util/ArrayList."<init>":()V
35: astore_3
36: aload_3
37: ldc #4; //String
39: invokeinterface #5, 2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
44: pop
45: aload_3
46: iconst_0
47: invokeinterface #6, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
52: checkcast #7; //class java/lang/String
55: astore 4
57: return
}
正如你所看到的(如果你有耐心),两者是相同的。
顺便说一句,在Java 7中这可能会变得更容易。proposal中有Project Coin用于“改进的通用实例创建类型推断”。如果它进行最终剪切,则语法为:
List<String> test = new ArrayList<>();
// or
Map<String, Object> test2 = new HashMap<>();
不太难打字,不是吗?
答案 1 :(得分:3)
冗余很烦人。您可能希望查看具有创建List
的工厂方法的Google Collections:
List<Double> doubleList = Lists.newLinkedList();