有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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) 个答案

  1. # 1 楼答案

    解析调用MyClass的构造函数是在编译时完成的。当编译器编译Test构造函数的代码时,它不知道T实际上是什么,它只知道保证它是Map<String, String>,因此它只能将构造函数调用绑定到接受Map的构造函数。 在代码中TTreeMap的知识只存在于方法main的主体内,而不是外部。例如,如果添加了{{CD2}}构造函数的第二个调用方,它实际上通过了^ {< CD10> },则会发生什么情况。p>

    Java泛型的工作方式是,对于所有可能的泛型参数值,泛型方法的代码只编译一次(并且在字节码中只出现一次),不像在其他语言中,每个泛型类型都有泛型方法的副本

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

    重载(这里的内容)只能在编译时通过查看参数的静态类型来工作

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