我的节目是
package stackoverflow;
public class Main {
public static void main(String[] args) {
String.valueOf(hoge());
}
static <E> E hoge() {
return (E) "hoge";
}
}
结果是
Exception in thread "main" java.lang.ClassCastException:
java.base/java.lang.String cannot be cast to [C
at stackoverflow.Main.main(Main.java:6)
我正在使用Java9。
hoge
的返回类型不明确。我认为应该是编译错误。
为什么编译器会选择String.valueOf(char[])
而不是String.valueOf(Object)
?
答案 0 :(得分:2)
有几个重载的String.valueOfs,其中只有两个具有对象参数valueOf(char [])和valueOf(Object),其他都是原始的,如String.valueOf(int)。由于确切的返回类型是未知的,但它是一个对象类型,编译器选择了valueOf(char [])。我不知道JLS的哪一部分解释了这种行为,但它与此类似:
public static void main(String[] args) {
x(null);
}
static void x(char[] x) {
System.out.println("char[]");
}
static void x(Object o) {
System.out.println("Object");
}
编译器选择char []
答案 1 :(得分:1)
当多个重载方法适用于方法解析时,选择了最具体的方法。
如果其中一个参数类型是通用的且不受限制的,或者null
,这会导致一些奇怪的行为,因为它们匹配任何声明的方法参数类型。
在您的情况下,char[]
中的valueOf(char[])
比Object
中的valueOf(Object)
更具体 - 这就是原因。
选择最具体的方法
如果多个成员方法都可访问且适用于a 方法调用,有必要选择一个提供 运行时方法调度的描述符。 Java编程 language使用选择最具体方法的规则。
该部分的结果详细说明了如何完成。
java.lang.Object
在这方面并不特别;您将在以下代码中遇到同样的问题:
public class Main {
private static String valueOf(Number x) {
return null;
}
private static String valueOf(Integer x) {
return null;
}
public static void main(String[] args) {
valueOf(hoge());
}
static <E> E hoge() {
return (E) "hoge";
}
}
在上述情况下,方法调用将转到valueOf(Integer)
,因为Integer
比Number
更具体。