Given the following interface and class:
public interface Interface<T> {
List<T> get(List<List<Object>> keys);
}
public class Cls implements Interface {
@Override
public List get(List<List<Object>> keys) {
return Collections.emptyList();
}
}
Results in a compile error:
TypeTest.java:[9,11] error: Cls is not abstract and does not override abstract method get(List) in Interface TypeTest.java:[12,20] error: name clash: get(List<List<Object>>) in Cls and get(List<List<Object>>) in Interface have the same erasure, yet neither overrides the other
But this works:
public interface Interface<T> {
List<T> get();
}
public class Cls implements Interface {
@Override
public List get() {
return Collections.emptyList();
}
}
as does this:
public interface Interface<T> {
List<T> get(List<List<Object>> keys);
}
public class Cls implements Interface {
@Override
public List get(List keys) {
return Collections.emptyList();
}
}
I don't understand this behaviour. The type erasure only applies to the type paramter T
, does it not? Why does missing out T
affect the unrelated List<List<Object>> keys
parameter?
You are getting a compiler error in your first example because of the type erasure that occurs with raw types. Section 4.8 of the JLS describes the circumstances under which using a raw type would yield type erasure:
and
Other clauses in this section also describe how the types of fields, return types of methods, and parameter types of methods are also subject to type erasure.
Moving on to Section 4.6 of the JLS, as referred above:
Therefore, the erasure of the method
get
isYour initial example will not compile because the method signature for
Cls'
sget
method,get(List<List<Object>>)
does not match the raw interface's method, and it doesn't implement the raw interface'sget
method.That is also why your second and third examples compile -- they properly override the raw interface
Interface
.Incidentally, to override the generic
Interface
interface without resorting to implementing the raw type, supply a type argument in theimplements
clause:Implementing it:
Or
Any reference type would work in
implements Interface<String>
, as long as the type matches the return type inget
. The clauseimplements Interface<Integer>
would work with the methodList<Integer> get(List<List<Object>> keys)
.In short, type erasure occurs for all parameterized types and generic types in a raw class/interface, regardless of whether they are related to the generic type parameters declared on class/interface.