gpt4 book ai didi

java - 为什么编译器不强制扩展接口(interface)的泛型的返回类型值?

转载 作者:行者123 更新时间:2023-12-04 03:51:24 24 4
gpt4 key购买 nike

public class Test {
public static void main(String... args) {
ClassB clazzB1 = getClassA(); // compile error
ClassB clazzB2 = getInterfaceC1(); // compile error
ClassB clazzB3 = getInterfaceC2(); // no compile error
}

public static <T extends ClassA> T getClassA() {
return (T) new ClassA() {};
}

public static InterfaceC getInterfaceC1() {
return new InterfaceC() {};
}

public static <T extends InterfaceC> T getInterfaceC2() {
return (T) new InterfaceC() {};
}

private static abstract class ClassA {

}

private static class ClassB {

}
}
public interface InterfaceC {
}

为什么 getInterfaceC2() 分配给 clazzB3 时不给出编译错误?这似乎应该而且是我希望发生的事情。

最佳答案

你总是可以这样做:

static class InterestingType extends ClassB implements InterfaceC {

}

然后有:

public static <T extends InterfaceC> T getInterfaceC2() {
return (T)new InterestingType();
}

这样调用:

ClassB clazzB3 = getInterfaceC2();

会起作用。在您的情况下,很明显它会中断,但编译器无法(轻松)证明这一点。因此,您的示例是允许的,但会在运行时失败。

编辑

编译器看这个:

ClassB clazzB1 = getClassA();

并看到 getClassA() 返回一个 T 定义为 T extends ClassA,其中 ClassA 是一个类。它还看到此 T 已分配给 ClassB,其中 ClassB 也是一个类。所以它必须创建一个既符合 ClassA 又符合 ClassB 的特定类型,类似于理论:

T extends ClassA & ClassB

但这是不可能的类型,因为没有人可以做到 ... extends ClassA, ClassB (这在 java 中根本不允许)。所以编译器失败了。事实上,如果你这样做:

javac  --debug=verboseResolution=all Test

你会在输出中看到类似这样的东西:

error: incompatible types: inference variable T has incompatible upper bounds ClassB,ClassA

另一方面,当编译器查看此代码时:ClassB clazzB3 = getInterfaceC2();,它会看到 getInterfaceC2() 返回:

T extends InterfaceC

结果被分配给ClassB,所以它最终可能是这种类型:

T extends ClassB & InterfaceC

这是完全有效的。 可以有这样的类型。我已经向您展示了您可以创建一个 InterestingType,但正如 Holger 所指出的,您可以通过以下方式自己传递这样一个理论类型:

ClassB clazzB3 = Test.<InterestingType>getInterfaceC2();

这称为指定“类型见证”。

关于java - 为什么编译器不强制扩展接口(interface)的泛型的返回类型值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64391346/

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