简体   繁体   English

为什么编译器不对扩展接口的泛型强制执行返回类型值?

[英]Why does the compiler not enforce the return type value for a generic that extends an interface?

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 {
}

Why does getInterfaceC2() not give a compile error when assigned to clazzB3?为什么 getInterfaceC2() 在分配给 clazzB3 时不会给出编译错误? It seems like it should and is something that I would like to have happen.看起来它应该并且是我希望发生的事情。

You can always do:你总是可以这样做:

static class InterestingType extends ClassB implements InterfaceC {

}

And then have :然后有:

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

As such calling:因此调用:

ClassB clazzB3 = getInterfaceC2();

would work.会工作。 In your case it is obvious to you that it will break, but the compiler can't prove that (easily).在您的情况下,很明显它会中断,但编译器无法证明(很容易)。 As such, your example is allowed, but will fail at runtime.因此,您的示例是允许的,但在运行时会失败。

EDIT编辑

The compiler looks at this:编译器看这个:

ClassB clazzB1 = getClassA();

and sees that getClassA() returns a T that is defined as T extends ClassA , where ClassA is a class .并看到getClassA()返回一个T作为被定义T extends ClassA ,其中ClassA是一类 It also sees that this T is assigned to ClassB , where ClassB is a class also .它还看到这个T被分配给ClassB ,其中ClassB也是一个类 So it has to create a certain type that will conform to both ClassA and ClassB , something like a theoretical :所以它必须创建一个符合ClassAClassB的特定类型,类似于理论上的:

T extends ClassA & ClassB

but that is an impossible type, since no one can do ... extends ClassA, ClassB (this is simply not allowed in java).但这是一种不可能的类型,因为没有人可以做到... extends ClassA, ClassB (这在 Java 中是不允许的)。 So the compiler fails.所以编译器失败了。 As a matter of fact if you do :事实上,如果你这样做:

javac  --debug=verboseResolution=all Test

you will see in the output, something like:您将在输出中看到,例如:

error: incompatible types: inference variable T has incompatible upper bounds ClassB,ClassA错误:不兼容的类型:推理变量 T 的上限不兼容 ClassB,ClassA

On the other hand, when the compiler looks at this : ClassB clazzB3 = getInterfaceC2();另一方面,当编译器查看此内容时: ClassB clazzB3 = getInterfaceC2(); , it sees that getInterfaceC2() returns: ,它看到getInterfaceC2()返回:

T extends InterfaceC

and the result is assigned to ClassB , so it ends up with may be this type:并将结果分配给ClassB ,因此最终可能是这种类型:

T extends ClassB & InterfaceC

which is perfectly valid.这是完全有效的。 There can be such a type.可以有这样的类型。 I've shown you that you can create one as InterestingType , but as Holger pointed out, you could pass such a theoretical type yourself, via:我已经向您展示了您可以创建一个InterestingType ,但正如 Holger 指出的那样,您可以通过以下方式自己传递这样一个理论类型:

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

this is called specifying a "type witness".这称为指定“类型见证”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java如何返回扩展接口的泛型类型 - Java how to return a generic type that extends an interface “扩展”接口的通用返回值是否等于仅作为返回值的接口? - Is a generic return value that "extends" an interface equal to just the interface as an returnvalue? 为什么Java编译器不让我返回泛型? - Why does the Java compiler not let me return a generic type? 为什么 ? 扩展...接受子作为返回值但不作为主要的变量类型? - Why does ? extends ... accept child for return value but not as a variable type in main? java泛型绑定类型-为什么扩展仅意味着扩展类并实现接口? - java generic bound type-why does extends only mean extending the classes and implementing the interface? 通用问题:T扩展接口类型。 无法调用方法返回扩展类型的对象? - Generic issues: T extends interface type. Cannot call method to return an object which extends the type? 为什么编译器在调用一个不相关的接口类型时会选择这个带有类类型参数的泛型方法? - Why does the compiler choose this generic method with a class type parameter when invoked with an unrelated interface type? Java:为什么泛型类不强制使用相同的类型? - Java: Why generic class does not enforce same type? Java 与 generics 的接口是否可以强制执行通用类型? - Is it possible for Java interface with generics to enforce the generic type? Java返回扩展接口的泛型类型 - Java returning generic type that extends an interface
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM