gpt4 book ai didi

java - 当使用不相关的接口(interface)类型调用时,为什么编译器会选择带有类类型参数的泛型方法?

转载 作者:行者123 更新时间:2023-12-02 08:12:30 25 4
gpt4 key购买 nike

考虑以下两个类和接口(interface):

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

如果 getInterface1Interface1 有,为什么第二次调用 mandatory 会调用 Class2 的重载方法与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 中,会推断出最具体的适用类型。 Java 8 的 JLS 引入了新章节 Chapter 18. Type Inference Java 7 的 JLS 中缺少这一点。

<小时/>

<T extends Interface1> 最具体的适用类型是 <X extends RequiredClass & BottomInterface> ,其中RequiredClass是上下文所需的类,并且 BottomInterface是所有接口(interface)的底层类型(包括 Interface1 )。

注意:每个 Java 类型都可以表示为 SomeClass & SomeInterfaces 。自 RequiredClassSomeClass 的子类型,和BottomInterfaceSomeInterfaces 的子类型, 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是所有接口(interface)的底层类型。

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

关于java - 当使用不相关的接口(interface)类型调用时,为什么编译器会选择带有类类型参数的泛型方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59430039/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com