【发布时间】:2013-08-26 23:27:39
【问题描述】:
据我所知,Java 在运行时会丢弃泛型类型参数信息。它仅在编译时用于执行检查,例如,此特定方法调用是否有效。
今天我遇到了以下一段代码,其中,Java 似乎通过集合/列表类型参数来确定要调用哪个构造函数:
public static class MyClass {
public MyClass(final Collection<String> coll) {
System.out.println("Constructor 1");
}
public MyClass(final List<Integer> list) {
System.out.println("Constructor 2");
}
}
进行了以下调用:
new MyClass(new HashSet<String>()); // Constructor 1
new MyClass(new ArrayList<String>()); // Constructor 1
new MyClass(new ArrayList<Integer>()); // Constructor 2
现在,如果我删除类型参数:
public static class MyClass2 {
public MyClass2(final Collection coll) {
System.out.println("Constructor 1");
}
public MyClass2(final List list) {
System.out.println("Constructor 2");
}
}
...和我期望的一样的调用;使用列表参数的构造函数调用适用于“最精确”满足其需求的构造函数:
new MyClass2(new HashSet<String>()); // Constructor 1
new MyClass2(new ArrayList<String>()); // Constructor 2
new MyClass2(new ArrayList<Integer>()); // Constructor 2
似乎泛型信息被存储在编译的类(在本例中为 MyClass)中,毕竟没有被丢弃,但它应该被丢弃。我误会了什么?
【问题讨论】:
-
+1 好问题。我对为什么会这样有一个模糊的想法,但我很高兴看到一个好的答案。
-
我猜这可能与 Java 选择在编译时使用的方法有关?
-
在编译时,编译器从一组重载方法中选择“最接近的匹配”。通用参数正在影响编译器用于进行选择的算法。
-
我将 MyClass 和 MyClass2 分离到一个单独的类中,编译它。然后把main方法放到一个单独的类中,编译并调用。结果是一样的。我想是存储了某种通用类型参数信息。