在 Java 中初始化泛型类的实例时,在语句的两边指定类型有什么好处吗?
或者换句话说,这两个有效语句之间有什么区别:
ArrayList<String> test = new ArrayList<String>();
和:
ArrayList<String> test = new ArrayList();
(似乎第二条语句不等同于:
ArrayList<String> test = new ArrayList<Object>();
作为无效的第三条语句并导致不兼容的类型
编译错误。)
最佳答案
第二个语句最终或多或少等同于第一个,但这只是因为泛型在运行时被删除。您会收到“未经检查的转换”警告,这就是我不喜欢它的原因。
更好的方法是使用这样的静态泛型方法:
public static <T> List<T> newList() {
return new ArrayList<T>();
}
然后做
List<String> test = newList();
这就是 Google Collections 所做的。
(而且您几乎应该始终将列表声明为 List
,而不是 ArrayList
。这样可以在以后轻松切换实现。)
编辑: dribeas 在评论中询问了这两个声明之间的确切区别是什么,以及为什么我说它们“或多或少等价”。因为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<>();
打字不难吧?
关于java - 在 Java 中创建泛型类实例的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/682092/