为什么这个分支会中断类型推断?
Why does this branch break type inference?
我在 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);
这两种方法可以正常编译和工作:
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());
});
}
错误:
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
(我删除了包限定符以使错误更具可读性)
我可以通过指定类型使其编译:
if (r.equals("x")) {
return Either.<Foo, Bar> left(new Foo());
}
return Either.<Foo, Bar> right(new Bar());
但我为什么需要这样做?我怎样才能避免这种代码混乱?
我没有看到你的整个 class 但这段代码为我编译:
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());
});
}
}
此代码应该有效。
它在最新的 JDK、1.8.0_121.
上编译
无法在 JDK 1.8.0-51 上编译。
这意味着它很可能是此版本 JDK 中的错误,因为除非修复错误,否则以后的版本不应更改编译器的行为。可能是错误 JDK-8055963.
所以,解决方案是:
- 升级你的编译器
- 如果您无法升级编译器(例如,其他人,固执的,拥有构建系统),请坚持使用您现有的明确类型的解决方法。
我在 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);
这两种方法可以正常编译和工作:
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());
});
}
错误:
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
(我删除了包限定符以使错误更具可读性)
我可以通过指定类型使其编译:
if (r.equals("x")) {
return Either.<Foo, Bar> left(new Foo());
}
return Either.<Foo, Bar> right(new Bar());
但我为什么需要这样做?我怎样才能避免这种代码混乱?
我没有看到你的整个 class 但这段代码为我编译:
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());
});
}
}
此代码应该有效。
它在最新的 JDK、1.8.0_121.
上编译无法在 JDK 1.8.0-51 上编译。
这意味着它很可能是此版本 JDK 中的错误,因为除非修复错误,否则以后的版本不应更改编译器的行为。可能是错误 JDK-8055963.
所以,解决方案是:
- 升级你的编译器
- 如果您无法升级编译器(例如,其他人,固执的,拥有构建系统),请坚持使用您现有的明确类型的解决方法。