Joh*_*uhn 6 java lambda type-inference jls
背景:最近我写了一个答案,建议我编写以下代码:
Files.write(Paths.get("PostgradStudent.csv"),
Arrays.stream(PGstudentArray).map(Object::toString).collect(Collectors.toList()),
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
Run Code Online (Sandbox Code Playgroud)
经过一番思考,我说:“我实际上不需要这里的列表,我只需要一个Iterable<? extends CharSequence>”。
就像Stream<T>一种方法一样Iterator<T> iterator(),然后我想到了,这很容易:
Iterable<? extends CharSequence> iterable = () -> Arrays.stream(arr).map(Object::toString).iterator();
Run Code Online (Sandbox Code Playgroud)
(针对这个问题,我将其提取到一个局部变量中,我想最后进行内联。)
不幸的是,如果没有其他类型提示,则无法编译该代码:
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>
Run Code Online (Sandbox Code Playgroud)
当然添加一些类型提示将使这项工作:
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();
Run Code Online (Sandbox Code Playgroud)
以我的理解,Java编译器执行以下操作:
Iterable<? extends CharSequence>。() -> Iterator<? extends CharSequence>在我的情况下。() -> Iterator<String>。有趣的是,如果我将lambda的目标更改为Supplier:
Supplier<Iterator<? extends CharSequence>> supplier = () -> Arrays.stream(arr)
.map(Object::toString)
.iterator();
Run Code Online (Sandbox Code Playgroud)
它将编译正常。
现在的问题是:为什么javac不能为此lambda推断正确的类型?
您可以在这里找到一些解释:
\n\n\n\n\n在检查兼容性之前,通配符参数化的函数接口类型必须转换为函数类型(方法签名)......其工作原理如下:
\n
Iterable<? extends CharSequence> becomes () -> Iterator<CharSequence>\nRun Code Online (Sandbox Code Playgroud)\n\n因此,如果 lambda 表达式是隐式类型的,则 LHS 变为 ,Iterator<CharSequence>而 RHS 为Iterator<String>。因此,出现错误:
Iterator<String> cannot be converted to Iterator<CharSequence>\nRun Code Online (Sandbox Code Playgroud)\n\nJLS \xc2\xa718.5.3中也解释了此行为。
\n| 归档时间: |
|
| 查看次数: |
113 次 |
| 最近记录: |