【发布时间】:2018-12-26 21:15:12
【问题描述】:
给定以下类:
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();} };
我想写一些UnaryOperators 可以接受 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 中可用的方法?
【问题讨论】:
-
为什么要这样做?不接受 D 的实例违反了en.wikipedia.org/wiki/Liskov_substitution_principle
-
op1 = (A arg) -> arg.a(); op2 = (B arg) -> arg.b() ... -
这只是为了更好地理解 java 编译器如何在涉及泛型的 lambda 表达式中推断类型。你对替代原则是正确的。只是因为据我所知,这种行为是极端情况,我想知道这种行为是否有正当理由。
-
您遇到的问题是 D 都是 C,但 A 是 Object,您无法在层次结构中定义范围供编译器检查,您需要添加运行时检查。
标签: java generics java-8 functional-programming bounded-wildcard