Why doesn't the following code produce a compile-time unchecked warning:
class Parent {
public List method(){
return null;
}
}
class Child extends Parent {
public List<String> method() {
return null;
}
}
while the following actually does:
class Parent {
public List<String> method(){
return null;
}
}
class Child extends Parent {
public List method() {
return null;
}
}
I'm actually looking for a reference for this behaviour in the JLS.
Because List is not a subtype of List<String> but (as you know) List<String> is a subtype of List.
Examples given in the JLS:
class C implements Cloneable {
C copy() throws CloneNotSupportedException {
return (C)clone();
}
}
class D extends C implements Cloneable {
D copy() throws CloneNotSupportedException {
return (D)clone();
}
}
This represents your first example where the return type in the child is a subtype of the parent. Likewise, in your example, List<String> is a subtype of List.
4.10.2. Subtyping among Class and Interface Types
Given a generic type declaration
C<F1,...,Fn>(n > 0), the direct supertypes of the generic typeC<F1,...,Fn>are all of the following:
- The direct superclass of
C<F1,...,Fn>.- The direct superinterfaces of
C<F1,...,Fn>.- The type
Object, ifC<F1,...,Fn>is a generic interface type with no direct superinterfaces.- The raw type
C. (boldness mine)
While:
class StringSorter {
// turns a collection of strings into a sorted list
List<String> toList(Collection<String> c) {...}
}
class Overrider extends StringSorter {
List toList(Collection c) {...}
}
is an example of your second snippet.
An unchecked warning would be given when compiling
Overrideragainst thenewdefinition ofStringSorterbecause the return type ofOverrider.toListisList, which is not a subtype of the return type of the overridden method,List<String>. (striking mine)
JLS examples 8.4.8.3-1 & 8.4.8.3-2 and specifically:
8.4.8.3. Requirements in Overriding and Hiding
If a method declaration d1 with return type R1 overrides or hides the declaration of another method d2 with return type R2, then d1 must be return-type-substitutable (§8.4.5) for d2, or a compile-time error occurs.
This rule allows for covariant return types - refining the return type of a method when overriding it.
If R1 is not a subtype of R2, a compile-time unchecked warning occurs unless suppressed by the
SuppressWarningsannotation (§9.6.4.5).