Why does this generic code compile?
Javac infers that T
is String
in method f()
. Which rules in language spec lead to that c开发者_如何学JAVAonclusion?
<T> T g(){ return null; }
String f()
{
return g();
}
I suspect the compiler is effectively using section 15.12.2.8:
If the method result occurs in a context where it will be subject to assignment conversion (§5.2) to a type S, then let R be the declared result type of the method
This is treating the return statement as if it were subject to assignment conversion. For example, imagine we converted f()
to:
String f()
{
String tmp = g();
return tmp;
}
Now as to whether it is subject to assignment conversion, section 14.17 (the return statement) contains this:
A return statement with an Expression must be contained in a method declaration that is declared to return a value (§8.4) or a compile-time error occurs. The Expression must denote a variable or value of some type T, or a compile-time error occurs. The type T must be assignable (§5.2) to the declared result type of the method, or a compile-time error occurs.
That reference to 5.2 is the "assignment conversion" section, so I guess that means the expression g()
is "subject to assignment conversion", leading to that part of section 15.12.2.8 being applicable.
T is inferred to be a String because the generic return type of g() is used as the return type of f(), which is strongly typed to a String. In order for the statement to be valid, T must be a String, so it is.
Because g is a generic method, Java infers the type of g to match the return type of f.
You can see this by trying the following three functions.
class SomeClass{
<T> T g(){return null;}
String f() {
return this.<String>g();
}
Integer h() {
return this.<Integer>g();
}
Integer i() {
return this.<String>g();
}
}
f and h will compile fine because it infers the type from the return type. i will not compile because the types do not match.
精彩评论