当前位置: 首页 > 面试题库 >

为什么此分支中断类型推断?

湛骏祥
2023-03-14
问题内容

我正在使用EitherJava 的本地实现,该实现具有如下方法:

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());

但是为什么我需要呢?以及如何避免此代码混乱?


问题答案:

此代码应该起作用。

它在最新的JDK 1.8.0_121上编译。

无法在JDK 1.8.0-51上编译

这意味着它在此版本的JDK中很可能是一个错误,因为更高版本的除非修正了一个错误,否则不应更改编译器的行为。可能是错误JDK-8055963。

因此,解决方案是:

  1. 升级您的编译器
  2. 如果您不能升级编译器(例如,其他人,固执己见,拥有构建系统),请坚持使用现有的变通方法来明确显示类型。


 类似资料:
  • 我使用的是Java中的<code>或者</code>的本地实现,它有如下方法: 这两种方法可以编译并正常工作: 此方法不编译: 错误: (我去掉了包限定符,使错误更加易读) 我可以通过指定类型来编译它: 但我为什么需要这样做?我如何避免这种代码混乱?

  • 问题内容: 说,我有一种方法: 然后在尝试编译此代码时: 我得到一个错误。谁能解释为什么类型系统不能推断Collections.emptyList()应该是类型吗? 上面的示例显然是很人为的,但是我一直都在偶然地遇到这种限制,这确实很烦人。阅读了 Effective Java 之后,我发现您可以轻松地完成工作(必须说,当时对我来说是一个启示),并且一切都可以顺利编译,但是当您使用复杂的类型时,确实

  • 说吧,我有一个方法: 然后在尝试编译此代码时: 我收到错误

  • 问题内容: 我有一个奇怪的场景,在使用lambda表达式时,类型推断无法按预期工作。这是我实际情况的近似值: 我倒数第二行的编译错误是 未为对象类型定义方法booleanValue() 如果我将lambda转换为: 或者如果我将方法签名更改为使用原始类型: 然后问题就解决了。我希望它能起作用的方式是: 调用应推断返回类型为 在lambda中应该推断为。 为什么这种推论不能按预期方式工作?如何更改此

  • 问题内容: 我知道在分配中使用泛型时,方法可以通过查看左侧变量的类型隐式地知道返回类型的类型。 来自Google收藏夹的示例: 我的问题是为什么它不适用于方法或更高类型的推理? 例: 是在JLS中指定的吗?如果是,为什么?如果没有,那么这是我可以期望从Java 7获得的一种改进吗? 这让我很烦,因为似乎我们在Java中遇到了问题,就像很久以前在Delphi中就遇到问题一样,在该问题中我无法进行链式

  • 看看下面例子中泛型类型的类型推断,我说不出为什么工作得很好,但是(几乎相同)无法编译,为了管理它,编译器需要额外的技巧,比如或。 导致编译器不确定表达式类型和方法结果类型是否兼容的问题是什么?