[英]Why does this branch break type inference?
I'm using a home-grown implementation of Either
in Java, which has a methods like this: 我在Java中使用了一个自行开发的Either
实现,它有一个像这样的方法:
public static <L, R> Either<L, R> left(final L value);
public static <L, R> Either<L, R> right(final R value);
public <T> T fold(
final Function<? super L, ? extends T> leftFunction,
final Function<? super R, ? extends T> rightFunction);
These two methods compile and work fine: 这两种方法编译并正常工作:
Either<Foo, Bar> rightToLeft() {
Either<Foo, Bar> input = Either.right(new Bar());
return input.fold(
l -> null,
r -> Either.left(new Foo())
);
}
Either<Foo, Bar> rightToRight() {
Either<Foo, Bar> input = Either.right(new Bar());
return input.fold(
l -> null,
r -> Either.right(new Bar())
);
}
This method does not compile: 此方法无法编译:
Either<Foo, Bar> rightToLeftOrRightConditionally() {
Either<Foo, Bar> 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());
});
}
Error: 错误:
incompatible types: inferred type does not conform to upper bound(s)
inferred: Either<? extends Object,? extends Object>
upper bound(s): Either<Foo,Bar>,java.lang.Object
(I've trimmed out the package qualifiers to make the error more readable) (我已经修剪了包限定符以使错误更具可读性)
I can make it compile by specifying the types: 我可以通过指定类型来编译它:
if (r.equals("x")) {
return Either.<Foo, Bar> left(new Foo());
}
return Either.<Foo, Bar> right(new Bar());
But why do I need to? 但为什么我需要? And how can I avoid this code clutter? 我怎样才能避免这种代码混乱?
This code should work. 这段代码应该有效。
It compiles on the latest JDK, 1.8.0_121. 它汇编了最新的JDK,1.8.0_121。
It fails to compile on JDK 1.8.0-51. 它无法在JDK 1.8.0-51上编译。
This means it's most likely a bug in this version of the JDK, since later versions should not change the behaviour of the compiler unless to fix a bug. 这意味着它很可能是此版本JDK中的一个错误,因为除非修复错误,否则更高版本不应更改编译器的行为。 It may be bug JDK-8055963 . 它可能是错误JDK-8055963 。
So, the solutions are: 所以,解决方案是:
I do not see your entire class but this code compiles for me: 我没有看到你的全班,但这段代码为我编译:
class Foo{}
class Bar{}
class Either<L,R> {
private L left;
private R right;
public Either(L left, R right) {
this.left = left;
this.right = right;
}
public static <L, R> Either<L,R> left(L l) {
return new Either<>(l, null);
}
public static <L, R> Either<L,R> right(R r) {
return new Either<>(null, r);
}
public <T> T fold(
final Function<? super L, ? extends T> leftFunction,
final Function<? super R, ? extends T> rightFunction) {
return null;
}
Either<Foo, Bar> rightToLeft() {
Either<Foo, Bar> input = Either.right(new Bar());
return input.fold(
l -> null,
r -> Either.left(new Foo())
);
}
Either<Foo, Bar> rightToRight() {
Either<Foo, Bar> input = Either.right(new Bar());
return input.fold(
l -> null,
r -> Either.right(new Bar())
);
}
Either<Foo, Bar> rightToLeftOrRightConditionally() {
Either<Foo, Bar> 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());
});
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.