给定以下类(class):
class A { public A a() {return new A();}; };
class B extends A { public B b() {return new B();} };
class C extends B { public C c() {return new C();} };
class D extends C { public D d() {return new D();} };
我想写一些UnaryOperator
可以接受 A、B 和 C 的实例,但不能接受 D。
所以我选择声明引用类型是 UnaryOperator<? super C>
。因为我正在使用 super
,这意味着它也可以接受 Object
的实例.
UnaryOperator<? super C> op1 = arg -> arg.a(); // does not compile, arg could be Object
UnaryOperator<? super C> op2 = arg -> arg.b(); // does not compile, arg could be Object
UnaryOperator<? super C> op3 = arg -> arg.c(); // does compile
UnaryOperator<? super C> op4 = arg -> arg.d(); // this is not expected to compile
为什么op1
使代码无法编译并显示一条消息
Type mismatch: cannot convert from A to C
和op2
使代码无法编译并显示一条消息
Type mismatch: cannot convert from B to C
,
但是op3
编译正常,让我调用一个仅在 C 中可用的方法?
最佳答案
Why does
op1
makes the code fail to compile...?
当通用函数接口(interface)通过通配符参数化时,有不同的实例化可以满足通配符并产生不同的函数类型。例如,每个 1:
UnaryOperator<C> (function type C -> C);
UnaryOperator<B> (function type B -> B);
UnaryOperator<A> (function type A -> A);
UnaryOperator<Object> (function type Object -> Object);
是UnaryOperator<? super C>
.
有时,可以从上下文中获知,例如 lambda 的参数类型,以及预期的函数类型。其他时候,需要选择一个:
UnaryOperator<? super C> op1 = (A arg) -> arg.a();
^
UnaryOperator<? super C> op2 = (B arg) -> arg.b();
^
...
如果您不选择一个,则使用边界2:
UnaryOperator<? super C> op = arg -> arg.c(); // valid
哪里C
是一个界限,所以 lambda 表达式是 UnaryOperator<C>
在这种情况下。
1 - JLS 9.9. Function Types - 最后一段。
2 - JLS 15.27.3. Type of a Lambda Expression - 如果T
是通配符参数化函数接口(interface)类型并且 lambda 表达式是隐式类型的,则基本目标类型是非通配符参数化 T
.
关于java - 捕获#1-of ? super C 解释为通用接口(interface)中的 C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51410687/