这是 Eclipse 编译器中的一个错误,兔子洞比编译器错误更深。我将您的代码示例简化为
public static void main(String[] args)
{
println(Stream.of(42).collect(Collectors.summingDouble(d -> d)));
}
public static void println(double x) {}
public static void println(char[] x) {}
public static void println(String x) {}
public static void println(Object x) {}
我只保留了println
影响编译器行为的方法。
有方法println(Object x)
,这是应该调用的,因为它是唯一适用的没有装箱操作的方法,println(double)
,这是错误消息中提到的并且在取消装箱后适用的方法,以及两种方法println(char[] x)
和println(String x)
,它们不适用一点也不。
删除println(double x)
方法会使错误消失,这是可以理解的,即使错误不正确,但奇怪的是,删除println(Object x)
方法并不能解决错误。
更糟糕的是,删除任何一个不适用的方法,println(char[] x)
或者println(String x)
,也会删除错误,但会生成调用错误的、不适用的方法的代码:
public static void main(String[] args)
{
println(Stream.of(42).collect(Collectors.summingDouble(d -> d)));
}
public static void println(double x) { System.out.println("println(double)"); }
public static void println(char[] x) { System.out.println("println(char[])"); }
//public static void println(String x) { System.out.println("println(String)"); }
public static void println(Object x) { System.out.println("println(Object)"); }
Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to [C
at Tmp2.main(Unknown Source)
public static void main(String[] args)
{
println(Stream.of(42).collect(Collectors.summingDouble(d -> d)));
}
public static void println(double x) { System.out.println("println(double)"); }
//public static void println(char[] x) { System.out.println("println(char[])"); }
public static void println(String x) { System.out.println("println(String)"); }
public static void println(Object x) { System.out.println("println(Object)"); }
Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.String
at Tmp2.main(Unknown Source)
我认为,我们不需要深入研究正式的 Java 语言规范,就可以认识到这种行为是不恰当的。
删除不适用的方法println(char[] x)
和println(String x)
会使编译器选择正确的方法println(Object x)
over println(double x)
,但这并不令人印象深刻。
作为参考,我使用版本 Oxygen.3a Release (4.7.3a) 进行了测试,构建 20180405-1200。可能还有其他版本受到影响。