为什么这个分支打破类型推断?
我正在使用Java中的Either
的本地实现,它具有如下方法:
public static Either left(final L value); public static Either right(final R value); public T fold( final Function leftFunction, final Function rightFunction);
这两种方法编译和工作正常:
Either rightToLeft() { Either input = Either.right(new Bar()); return input.fold( l -> null, r -> Either.left(new Foo()) ); } Either rightToRight() { Either input = Either.right(new Bar()); return input.fold( l -> null, r -> Either.right(new Bar()) ); }
此方法无法编译:
Either rightToLeftOrRightConditionally() { Either input = Either.right(new Bar()); return input.fold( l -> null, r -> { if (r.equals("x")) { return Either.left(new Foo()); } return Either.right(new Bar()); }); }
错误:
incompatible types: inferred type does not conform to upper bound(s) inferred: Either upper bound(s): Either,java.lang.Object
(我已经修剪了包限定符以使错误更具可读性)
我可以通过指定类型来编译它:
if (r.equals("x")) { return Either. left(new Foo()); } return Either. right(new Bar());
但为什么我需要? 我怎样才能避免这种代码混乱?
这段代码应该有效。
它汇编了最新的JDK,1.8.0_121。
它无法在JDK 1.8.0-51上编译。
这意味着它很可能是此版本JDK中的一个错误,因为除非修复错误,否则更高版本不应更改编译器的行为。 它可能是错误JDK-8055963 。
所以,解决方案是:
- 升级你的编译器
- 如果您无法升级编译器(例如,其他人,顽固,拥有构建系统),请坚持使用现有的解决方法来使类型显式化。
我没有看到你的全class,但这段代码为我编译:
class Foo{} class Bar{} class Either { private L left; private R right; public Either(L left, R right) { this.left = left; this.right = right; } public static Either left(L l) { return new Either<>(l, null); } public static Either right(R r) { return new Either<>(null, r); } public T fold( final Function super L, ? extends T> leftFunction, final Function super R, ? extends T> rightFunction) { return null; } Either rightToLeft() { Either input = Either.right(new Bar()); return input.fold( l -> null, r -> Either.left(new Foo()) ); } Either rightToRight() { Either input = Either.right(new Bar()); return input.fold( l -> null, r -> Either.right(new Bar()) ); } Either rightToLeftOrRightConditionally() { Either input = Either.right(new Bar()); return input.fold(l -> null, r -> { if (r.equals("x")) { return Either.left(new Foo()); } return Either.right(new Bar()); }); } }