Java通用方法.为什么T推断为Map?

Jos*_* D. 6 java generics methods

请考虑以下代码

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>());
    }

}
Run Code Online (Sandbox Code Playgroud)

它打印map.为什么T推断为Map,而不是SortedMappublic <T extends Map<String, String>> Test(T t)?有没有办法改变这种行为,以便使用最具体的构造函数MyClass

Phi*_*ler 4

调用哪个构造函数的解析MyClass是在编译时完成的。当编译器编译构造函数的代码时Test,它不知道T实际是什么,它只知道它保证是 a Map<String, String>,因此除了将构造函数调用绑定到采用 a 的构造函数之外,它不能做任何其他事情Map。代码中Ta的知识TreeMap仅存在于方法体内main,而不存在于外部。例如,考虑一下如果您添加了Test实际传递HashMap.

Java 泛型的工作原理是,泛型方法的代码仅针对所有可能的泛型参数值编译一次(并且仅在字节代码中出现一次),不像其他语言那样为每个泛型类型提供泛型方法的副本。

一般来说,在Java中不可能让代码中的单个方法/构造函数调用在运行时根据参数的类型实际调用不同的方法/构造函数。这仅适用于方法调用,具体取决于被调用对象的运行时类型(与覆盖方法的动态绑定)。

重载(这里的内容)仅在编译时通过查看参数的静态类型起作用。

这种情况的典型解决方案是instanceof SortedMap在 的构造函数中使用检查MyClass。另一种可能的(更优雅的)解决方案是访问者模式,但这仅适用于为其准备的类(因此,Map如果您不将实例包装在您自己的类中,则不适用于实例)。

  • 哦,我期望在同一个通用方法中为不同版本的“T”生成不同的代码。我猜Java不是C++。感谢您的回答,现在清楚了。 (2认同)