Java通用方法。为什么T被推断为地图?
考虑下面的代码
class MyClass {
public MyClass(Map<String, String> m) {
System.out.println("map");
}
public MyClass(SortedMap<String, String> m) {
System.out.println("sortedmap");
}
}
public class Test {
public <T extends Map<String,String>> Test(T t) {
new MyClass(t);
}
public static void main(String[] args) {
new Test(new TreeMap<String,String>());
}
}
它打印map
。为什么T
被推断为Map
而不是public <T extends Map<String, String>> Test(T t)
中的SortedMap
?有没有办法改变这种行为,以便为MyClass
使用最具体的构造函数
# 1 楼答案
解析调用
MyClass
的构造函数是在编译时完成的。当编译器编译Test
构造函数的代码时,它不知道T
实际上是什么,它只知道保证它是Map<String, String>
,因此它只能将构造函数调用绑定到接受Map
的构造函数。 在代码中T
是TreeMap
的知识只存在于方法main
的主体内,而不是外部。例如,如果添加了{{CD2}}构造函数的第二个调用方,它实际上通过了^ {< CD10> },则会发生什么情况。p>Java泛型的工作方式是,对于所有可能的泛型参数值,泛型方法的代码只编译一次(并且在字节码中只出现一次),不像在其他语言中,每个泛型类型都有泛型方法的副本
通常,在Java中,不可能让代码中的单个方法/构造函数调用在运行时根据参数类型实际调用不同的方法/构造函数。这仅适用于方法调用,具体取决于被调用对象的运行时类型(覆盖方法的动态绑定)
重载(这里的内容)只能在编译时通过查看参数的静态类型来工作
这种情况的典型解决方案是在
MyClass
的构造函数中使用instanceof SortedMap
检查。 另一个可能的(更优雅的)解决方案是visitor模式,但这只适用于为它准备的类(因此,如果不将Map
实例包装到自己的类中,则不适用于它们)