英文:
Explicit type hint in method reference lambda results in raw type
问题
用显式类型的通用方法引用来映射一个Optional似乎会导致某些情况下类型推断失败。在以下示例中,第一行编译通过,而当将List::of
方法给予显式类型,如List::<String>of
时,它无法编译通过:
Optional.of("one,two").map(List::of).get().get(0).split(",");
// 没有问题,类型推断正常工作
Optional.of("one,two").map(List::<String>of).get().get(0).split(",");
// 编译错误,因为映射后的Optional变成了带有原始List参数的类型(Optional<List>)
在上述情况下,对List::of
的类型提示是不必要的,但有许多情况下是需要的,为了帮助编译器,必须对映射进行类型提示,导致更加冗长的写法:
Optional.of("one,two").<List<String>>map(List::of).get().get(0).split(",");
一个案例是如果我们有一些类似于Either
的类型:
static class Either<L, R> {
L left;
R right;
private Either(final L left, final R right) {
this.left = left;
this.right = right;
}
static <L, R> Either<L, R> left(final L l) {
return new Either<>(l, null);
}
static <L, R> Either<L, R> right(final R r) {
return new Either<>(null, r);
}
}
然后:
final String right =
Optional.of("one,two")
.map(Either::<String, String>left)
.orElse(Either.right("three,four"))
.right;
无法编译通过,而需要这样做:
final String right =
Optional.of("one,two")
.<Either<String, String>>map(Either::left)
.orElse(Either.right("three,four"))
.right;
为什么会这样,是否有计划更改这个问题?
更新:
我正在使用OpenJDK 15,但这似乎是IntelliJ的问题 - 从命令行运行javac时,所有这些都可以编译,但IntelliJ错误地将上述某些行标记为编译错误。我将关闭并报告此问题。
英文:
Mapping an Optional with an explicitly typed generic method reference seem to cause type inference to fail in some cases. In the following example the first line compiles whereas when giving the List::of
-method an explicit type with List::<String>of
it does not compile:
Optional.of("one,two").map(List::of).get().get(0).split(",");
// No problem, type inference works fine
Optional.of("one,two").map(List::<String>of).get().get(0).split(",");
// Compiler error, because the mapped Optional becomes typed with a raw List parameter (Optional<List>)
In the above case the type hint to List::of was unnecessary, but there are many cases where it is needed and to help the compiler one has to type hint the map, resulting in the much more verbose
Optional.of("one,two").<List<String>>map(List::of).get().get(0).split(",");
One case would be if we had some Either type like
static class Either<L, R> {
L left;
R right;
private Either(final L left, final R right) {
this.left = left;
this.right = right;
}
static <L, R> Either<L, R> left(final L l) {
return new Either<>(l, null);
}
static <L, R> Either<L, R> right(final R r) {
return new Either<>(null, r);
}
}
then
final String right =
Optional.of("one,two")
.map(Either::<String, String>left)
.orElse(Either.right("three,four"))
.right;
fails to compile, instead one has to do
final String right =
Optional.of("one,two")
.<Either<String, String>>map(Either::left)
.orElse(Either.right("three,four"))
.right;
Why is it so and are there any plans to change this?
Update:
I am using OpenJDK 15, but this seems to be a problem in Intellij - running javac from the command-line all of this compiles, but Intellij erroneously highlights some of the above lines as compile errors. I will close and report a bug.
答案1
得分: 2
这原来是IntelliJ中的一个错误。
链接:https://youtrack.jetbrains.com/issue/IDEA-252839
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论