我似乎已经成功地打破了Java的类型推断,代码如下:
public static void main (String[] args)
{
final VirtualFS vfs = new VirtualFS();
vfs.addDirHandler(vf -> {
// top level directory only,
// return a list of all tags
return Arrays.stream("@tag_one @tag_two @tag_three".split(" +"))
.map(str -> (vf.getName() + str))
.map(str -> new VirtualFile(str)) // <-- here
.toList();
});
...
}
以上工作正常,但如果我将标记行更改为:
.map(VirtualFile::new) // <-- here
...然后它拒绝编译(尽管 IDE 不会抱怨它)。我还可以通过向之前的 .map 操作添加
(String)
转换来解决该问题。
.getName()
中的VirtualFile
方法返回一个String
。 Java版本是17,我的IDE是Intellij IDEA。就像我说的,我可以通过强制转换来解决问题,但我很好奇到底发生了什么混淆了类型推断。
我得到的编译器错误是:
java: incompatible types: invalid constructor reference
incompatible types: java.lang.Object cannot be converted to java.lang.String
最小可重现示例:
import java.util.function.Function;
import java.util.*;
public class VirtualFile
{
private final String name;
public VirtualFile(String name)
{
this.name = name;
}
public String getName () { return this.name; }
private static class VirtualFS
{
public void addDirHandler (Function<VirtualFile, List<VirtualFile>> fn)
{
}
}
public static void main (String[] args)
{
final VirtualFS vfs = new VirtualFS();
vfs.addDirHandler(vf -> {
// top level directory only,
// return a list of all tags
return Arrays.stream("@tag_one @tag_two @tag_three".split(" +"))
.map(str -> vf.getName() + str)
.map(VirtualFile::new)
.toList();
});
}
}
这似乎是编译器错误 JDK-8268312,如果您在另一个采用
Function
(如 Stream.map
)的方法的 lambda 参数中调用采用 Function
(如 (addDirHandler
))的方法,前一个调用的类型信息丢失。
这在 Java 20 中已修复。