Optional.orElse 不使用匿名类型进行编译



我在使用Optionals和匿名类时遇到了一个奇怪的问题:

public class Foo {
interface Bar {
}
void doesNotCompile() {
Optional.of(new Bar() {
}).orElse(new Bar() {
});
}
void doesNotCompile2() {
final Bar bar = new Bar() {
};
Optional.of(new Bar() {
}).orElse(bar);
}
void compiles1() {
final Bar bar = new Bar() {
};
Optional.of(bar).orElse(new Bar() {
});
}
}

前两种方法不会编译并出现错误

java: incompatible types: <anonymous test.Foo.Bar> cannot be converted to <anonymous test.Foo.Bar>

我早就预料到了,因为两者都实现了接口Bar这三种方法都有效。我也无法弄清楚为什么第三个选项可以解决问题。谁能解释一下?

可以使用类型见证来补充前两个类型:

Optional.<Bar>of(new Bar(){}).orElse(new Bar(){});

这允许编译器看到你期望返回Optional<Bar>,然后 #orElse 可以推断接受任何Bar

您需要告诉可选,您需要为该接口提供一个栏。

Bar bar = new Bar();
Optional<Bar> o = Optional.of(new Bar() {}).orElse(bar);

案例compiles1

您的Optional具有泛型类型Bar,因为变量bar的类型为Bar

您创建的类型Foo$1的匿名类具有Bar为超类型,因此该方法将进行编译。

案例doesNotCompile

在这里,Optional具有泛型类型Foo$1,并且您正在尝试将类型为Foo$2的对象传递到没有Foo$1作为超类型的orElse对象中。因此编译错误。

案例doesNotCompile2

doesNotCompile类似,Optional具有泛型类型Foo$1,并且您正在尝试将bar,一个类型为Bar的变量传递到orElse中,而该变量同样没有Foo$1作为超类型。


避免这些错误

将类型见证添加到Optional::of调用中。这会为您的Optional提供泛型类型Bar

public class Foo {
interface Bar {
}
void doesNotCompile() {
Optional.<Bar>of(new Bar() {
}).orElse(new Bar() {
});
}
void doesNotCompile2() {
final Bar bar = new Bar() {
};
Optional.<Bar>of(new Bar() {
}).orElse(bar);
}
void compiles1() {
final Bar bar = new Bar() {
};
Optional.of(bar).orElse(new Bar() {
});
}
}

最新更新