为什么这个分支打破类型推断?

我正在使用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 。

所以,解决方案是:

  1. 升级你的编译器
  2. 如果您无法升级编译器(例如,其他人,顽固,拥有构建系统),请坚持使用现有的解决方法来使类型显式化。

我没有看到你的全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 leftFunction, final Function 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()); }); } }