Reputation:
My program is
package stackoverflow;
public class Main {
public static void main(String[] args) {
String.valueOf(hoge());
}
static <E> E hoge() {
return (E) "hoge";
}
}
result is
Exception in thread "main" java.lang.ClassCastException:
java.base/java.lang.String cannot be cast to [C
at stackoverflow.Main.main(Main.java:6)
I'm using Java9.
The return type of hoge
is ambiguous. I think it should be compile error.
And why compiler choose String.valueOf(char[])
instead of String.valueOf(Object)
?
Upvotes: 0
Views: 291
Reputation: 31269
When multiple overloaded methods are applicable for method resolution, the most specific method is chosen.
This can result in some odd behaviour if one of the argument types is generic and unrestricted, or null
, because they match any declared method argument type.
In your case, char[]
in valueOf(char[])
is more specific than Object
in valueOf(Object)
- that's the reason.
This is specified in JLS 15.12.2.5
Choosing the Most Specific Method
If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.
The result of the section goes into detail how this is done.
java.lang.Object
is not special in this respect; you'll get the same issue with the following code:
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";
}
}
In the above case, the method call will go to valueOf(Integer)
because Integer
is more specific than Number
.
Upvotes: 0
Reputation: 135992
There are several overloaded String.valueOfs, only two of them have object parameter valueOf(char[]) and valueOf(Object), others are primitive, like String.valueOf(int). Since exact return type is unknown, but it's an object type, compiler has chosen valueOf(char[]). I do not know which part of JLS explains that behavior, but it is similar to this:
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");
}
compiler chooses char[]
Upvotes: 1