Java 泛型捕获组

Java generics capture group

我在正确使用 Java 捕获组时遇到问题。

假设我有这些 类:

class Foo{}
class Bar{}

interface InterfaceXYZ<T>{ 
  void doSomething(T t);
}

class FooImplementation implements InterfaceXYZ<Foo>{
  @Override void doSomething(Foo){}
}

最后,

class Delegator<T>{
  Delegator(InterfaceXYZ<T> delegate){this.delegate = delegate;}

  void doSomething(T t) {
    delegate.doSomething(t);
  }

  private InterfaceXYZ<T> delegate;
}

问题是这工作正常 -

FooImplementation fi = new FooImplementation();
Delegator d = new Delegator(fi);
d.doSomething(new Foo());

这不能正常工作(如预期的那样)- 导致运行时异常

FooImplementation fi = new FooImplementation();
Delegator d = new Delegator(fi);
d.doSomething(new Bar());

为什么它不抛出编译时错误?如果我必须让它抛出编译时错误,我需要做哪些更改?

大部分是对的,但需要在实例化时指定<...>部分(否则会默认为原始类型,类似于。参见this answer有关 raw、 之间区别的详细信息)。 Foo 和 Bar 都是对象,因此编译器看到了这一点并认为没问题。

这是使用 <...> 进行实例化的样子。这里,InterfaceXYZ<Foo> 和 FooImplementation 可以互换(因为编译器知道 FooImplementation 是 InterfaceXYZ<Foo>

对于 Foo

InterfaceXYZ<Foo> fi = new FooImplementation();
Delegator<Foo> d = new Delegator<Foo>(fi);
d.doSomething(new Foo());

对于 Bar(获取编译时错误而不是运行时错误)

InterfaceXYZ<Bar> fi = new FooImplementation();
Delegator<Bar> d = new Delegator<Bar>(fi);
d.doSomething(new Bar());

补充说明:

InterfaceXYZ<?> fi = new FooImplementation(); 不会引发编译时错误,因为您可能会说将 fi 添加到 List<InterfaceXYZ<?>>,其中 InterfaceXYZ<bar> 也是有效且可用的。编译器不能也不会检查对象在调用堆栈中的所有可能使用方式,因此只相信编译时错误只会出现在当前 class 正在编译的上下文中。