Reputation: 2973
I have a class with generics. I know that generic type information is stripped at runtime, but this is with a bound type. I thought that at compilation java.lang.Object
is replaced with the bound type. If I know that everything will always be at least an Animal
, then why does the compiler leave it as Object
? Is there something I'm missing that would make this work like I want? Specifically, that last for
loop in the main method has a compile-time problem.
Thanks!
public static void main( String[] args ) throws Exception {
Litter<Cat> catLitter = new Litter<>();
for( Cat cat : catLitter ) {}
Litter<Animal> animalLitter = new Litter<>();
for( Animal animal : animalLitter ) {}
Litter litter = new Litter();
for( Animal animal : litter ) {} // Type mismatch: cannot convert from element type Object to Animal
}
public class Litter<T extends Animal> implements Iterable<T>{
@Override public java.util.Iterator<T> iterator() {
return new LitterIterator();
}
class LitterIterator implements java.util.Iterator<T> {
@Override public boolean hasNext() { return false; }
@Override public T next() { return null; }
}
}
public class Animal {}
public class Dog extends Animal{}
public class Cat extends Animal{}
Upvotes: 2
Views: 215
Reputation: 280138
Mandatory redirection:
The behavior you're expecting would apply to something like
public class Litter<T extends Animal> implements Iterable<T>{
public T get() {return null; /* or whatever */}
...
}
and
Litter litter = ...; // raw type
Animal animal = litter.get(); // compiles fine
Since Litter
is a raw type and
The type of a constructor (§8.8), instance method (§8.4, §9.4), or non-static field (§8.3) of a raw type
C
that is not inherited from its superclasses or superinterfaces is the raw type that corresponds to the erasure of its type in the generic declaration corresponding toC
and since
The erasure of a type variable (§4.4) is the erasure of its leftmost bound.
then the method get
appears as
public Animal get() {...}
to code using the raw Litter
type.
As for Litter#iterator()
however, its return type is Iterator<T>
and since
The erasure of a parameterized type (§4.5)
G<T1,...,Tn>
is|G|
.
its erasure is just Iterator
. The next()
method of Iterator
is then erased to
public Object next() {...}
so obviously its return value cannot be assigned to a variable of type Animal
.
Is there something I'm missing that would make this work like I want?
Not with raw types, no.
Upvotes: 4