当前位置: 首页 > 知识库问答 >
问题:

为什么这个分支会中断类型推理?

鲁杜吟
2023-03-14

我使用的是Java中的<code>或者</code>的本地实现,它有如下方法:

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

但我为什么需要这样做?我如何避免这种代码混乱?

共有2个答案

长孙高远
2023-03-14

我看不到您的整个类,但是这段代码为我编译了:

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());
        });
    }
}
翟嘉祥
2023-03-14

此代码应该有效。

它在最新的JDK1.8.0_121上编译。

它无法在JDK 1.8.0-51上编译。

这意味着这很可能是JDK这个版本中的一个错误,因为以后的版本不应该改变编译器的行为,除非修复一个错误。可能是JDK-8055963错误。

因此,解决方案是:

  1. 升级您的编译器
  2. 如果您无法升级编译器(例如,其他人,顽固,拥有构建系统),请坚持使用现有的解决方法,使类型显式。
 类似资料:
  • 问题内容: 我正在使用Java 的本地实现,该实现具有如下方法: 这两种方法可以编译并正常工作: 此方法无法编译: 错误: (我已经修剪了包限定符,以使错误更易读) 我可以通过指定类型进行编译: 但是为什么我需要呢?以及如何避免此代码混乱? 问题答案: 此代码应该起作用。 它在最新的JDK 1.8.0_121上编译。 无法在JDK 1.8.0-51上编译。 这意味着它在此版本的JDK中很可能是一个

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

  • 我有一个奇怪的场景,当使用lambda表达式时,类型推断没有像我预期的那样工作。以下是我真实场景的近似值: 我在倒数第二行得到的编译错误是 方法booleanValue()未为类型Object定义 如果我将lambda转换为

  • 我正在阅读新发布的Java 8在行动中,发现有一段从第5章粘贴的代码没有编译: Eclipse说:“类型不匹配:无法从< code >列表转换 在与作者在Github上给出的内容进行比较后,编译如下: 唯一的变化是从“j”到“(整数j)”。 但是,第一个版本与第二个版本在Java8提供的语法糖中不是完全相同吗?为什么Java拒绝编译它? 谢谢 顺便说一句:

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

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