方法引用 lambda 中的显式类型提示导致原始类型。

huangapple go评论75阅读模式
英文:

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::&lt;String&gt;of it does not compile:

Optional.of(&quot;one,two&quot;).map(List::of).get().get(0).split(&quot;,&quot;);
// No problem, type inference works fine

Optional.of(&quot;one,two&quot;).map(List::&lt;String&gt;of).get().get(0).split(&quot;,&quot;);
// Compiler error, because the mapped Optional becomes typed with a raw List parameter (Optional&lt;List&gt;)

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(&quot;one,two&quot;).&lt;List&lt;String&gt;&gt;map(List::of).get().get(0).split(&quot;,&quot;);

One case would be if we had some Either type like

static class Either&lt;L, R&gt; {
  L left;
  R right;

  private Either(final L left, final R right) {
    this.left = left;
    this.right = right;
  }

  static &lt;L, R&gt; Either&lt;L, R&gt; left(final L l) {
    return new Either&lt;&gt;(l, null);
  }

  static &lt;L, R&gt; Either&lt;L, R&gt; right(final R r) {
    return new Either&lt;&gt;(null, r);
  }
}

then

final String right =
    Optional.of(&quot;one,two&quot;)
        .map(Either::&lt;String, String&gt;left)
        .orElse(Either.right(&quot;three,four&quot;))
        .right;

fails to compile, instead one has to do

final String right =
    Optional.of(&quot;one,two&quot;)
        .&lt;Either&lt;String, String&gt;&gt;map(Either::left)
        .orElse(Either.right(&quot;three,four&quot;))
        .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

英文:

This turned out to be a bug in Intellij.

https://youtrack.jetbrains.com/issue/IDEA-252839

huangapple
  • 本文由 发表于 2020年10月14日 00:46:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/64339622.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定