为什么编译器在使用不相关的接口类型调用时选择带有类类型参数的通用方法?

问题描述 投票:4回答:1

请考虑以下两个类和接口:

public class Class1 {}
public class Class2 {}
public interface Interface1 {}

如果mandatoryClass2getInterface1没有关系,为什么对Interface1的第二个调用为什么用Class2调用重载方法?

public class Test {

    public static void main(String[] args) {
        Class1 class1 = getClass1();
        Interface1 interface1 = getInterface1();

        mandatory(getClass1());     // prints "T is not class2"
        mandatory(getInterface1()); // prints "T is class2"
        mandatory(class1);          // prints "T is not class2"
        mandatory(interface1);      // prints "T is not class2"
    }

    public static <T> void mandatory(T o) {
        System.out.println("T is not class2");
    }

    public static <T extends Class2> void mandatory(T o) {
        System.out.println("T is class2");
    }

    public static <T extends Class1> T getClass1() {
        return null;
    }

    public static <T extends Interface1> T getInterface1() {
        return null;
    }
}

我了解Java 8 broke compatibility与Java 7:

$ /usr/lib/jvm/java-8-openjdk-amd64/bin/javac -source 1.7 -target 1.7 *java; /usr/lib/jvm/java-8-openjdk-amd64/bin/java Test
warning: [options] bootstrap class path not set in conjunction with -source 1.7
1 warning
T is not class2
T is not class2
T is not class2
T is not class2

并且使用Java 8(也已通过11和13测试:)

$ /usr/lib/jvm/java-8-openjdk-amd64/bin/javac *java; /usr/lib/jvm/java-8-openjdk-amd64/bin/java Test                        
T is not class2
T is class2
T is not class2
T is not class2
java generics java-8 language-lawyer javac
1个回答
0
投票

Java编译器假定可能存在扩展Class2并实现Interface1的类:

public class Class3 extends Class2 implements Interface1 {}

因此,它决定getInterface1()返回与public static <T extends Class2> void mandatory(T o)签名匹配的对象:

mandatory(Test.<Class3>getInterface1()); // T is class2

mandatory(Test.<T>getInterface1())处得到相同结果的情况下调用T extends Class2 & Interface1:>

public static <T extends Class2 & Interface1> void helper() {
    mandatory(Test.<T>getInterface1()); // T is class2
}

mandatory(getClass1())不会一样,因为Class3不能同时扩展Class1Class2

© www.soinside.com 2019 - 2024. All rights reserved.