请考虑以下两个类和接口:
public class Class1 {}
public class Class2 {}
public interface Interface1 {}
如果mandatory
和Class2
与getInterface1
没有关系,为什么对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 8中得到了重大改进,最显着的是目标类型推断得到了很大的改进。因此,尽管在Java 8之前方法自变量站点未接收到任何推断,默认为擦除类型(Class1
为getClass1()
,Interface1
为getInterface1()
),但在Java 8中,推断出最具体的适用类型。 JLS for Java 8引入了新章Chapter 18. Type Inference,而JLS for Java 7中缺少该章。
<T extends Interface1>
的最适用类型是<X extends RequiredClass & BottomInterface>
,其中RequiredClass
是上下文所需的类,BottomInterface
是所有接口(包括Interface1
)的底部类型。
注:每种Java类型都可以表示为SomeClass & SomeInterfaces
。由于RequiredClass
是SomeClass
的子类型,并且BottomInterface
是SomeInterfaces
的子类型,所以X
是每种Java类型的子类型。因此,X
是Java底部类型。
[X
匹配public static <T> void mandatory(T o)
和public static <T extends Class2> void mandatory(T o)
方法签名,因为X
是Java底部类型。
因此,根据§15.12.2,mandatory(getInterface1())
调用了mandatory()
方法的最具体的重载,即public static <T extends Class2> void mandatory(T o)
,因为<T extends Class2>
比<T>
更具体。
这里是您可以显式指定getInterface1()
类型参数以使其返回与public static <T extends Class2> void mandatory(T o)
方法签名匹配的结果的方式:
public static <T extends Class2 & Interface1> void helper() {
mandatory(Test.<T>getInterface1()); // prints "T is class2"
}
<T extends Class1>
的最特定适用类型是<Y extends Class1 & BottomInterface>
,其中BottomInterface
是所有接口的底部类型。
Y
匹配public static <T> void mandatory(T o)
方法签名,但不匹配public static <T extends Class2> void mandatory(T o)
方法签名,因为Y
不扩展Class2
。
因此mandatory(getClass1())
调用public static <T> void mandatory(T o)
方法。
与getInterface1()
不同,您不能显式指定getClass1()
类型参数以使其返回与public static <T extends Class2> void mandatory(T o)
方法签名匹配的结果:
java: interface expected here
↓
public static <T extends Class1 & C̲l̲a̲s̲s̲2> void helper() {
mandatory(Test.<T>getClass1());
}