Java编译器为什么不能从约束推断Iterable Iterable扩展CharSequence>和()->(Iterator ) ] >>

问题描述 投票:6回答:2

背景:我最近写了an answer,建议在其中编写以下代码:

Files.write(Paths.get("PostgradStudent.csv"),
        Arrays.stream(PGstudentArray).map(Object::toString).collect(Collectors.toList()),
        StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);

经过一番思考,我说:“我实际上不需要这里的清单,我只需要一个Iterable<? extends CharSequence>”。由于Stream<T>具有方法Iterator<T> iterator(),因此我认为很简单:

Iterable<? extends CharSequence> iterable = () -> Arrays.stream(arr).map(Object::toString).iterator();

((针对该问题,我将其提取到一个局部变量中,我想最后进行内联。)不幸的是,如果没有其他类型提示,就无法编译:

error: incompatible types: bad return type in lambda expression
Iterable<? extends CharSequence> iterable = () -> Arrays.stream(arr).map(Object::toString).iterator();
                                                                                                   ^
    Iterator<String> cannot be converted to Iterator<CharSequence>

当然添加一些类型提示将使这项工作有效:

Iterable<? extends CharSequence> iterable2 = (Iterable<String>) () -> Arrays.stream(arr).map(Object::toString).iterator();
Iterable<? extends CharSequence> iterable3 = () -> Arrays.stream(arr).<CharSequence>map(Object::toString).iterator();

据我所知,Java编译器执行以下操作:

  1. 它查看表达式的目标类型,即Iterable<? extends CharSequence>
  2. 然后确定此接口的功能类型,在我的情况下为() -> Iterator<? extends CharSequence>
  3. 然后,它查看lambda并检查其是否兼容。在我的情况下,lambda的类型为() -> Iterator<String>。与步骤2中确定的功能类型兼容。
  4. 有趣的是,如果我将lambda的目标更改为Supplier

Supplier<Iterator<? extends CharSequence>> supplier = () -> Arrays.stream(arr)
    .map(Object::toString)
    .iterator();

它将编译良好。

现在的问题是:为什么Javac不能为此Lambda推断正确的类型?

[背景:我最近写了一个答案,建议我编写以下代码:Files.write(Paths.get(“ PostgradStudent.csv”),Arrays.stream(PGstudentArray).map(Object :: toString).collect(。 ..

java lambda type-inference jls
2个回答
3
投票

您可以找到一些解释here


0
投票

在阅读了另一个答案(绝对正确)和一些咖啡后,错误中的解释似乎是合乎逻辑的。

© www.soinside.com 2019 - 2024. All rights reserved.