简体   繁体   中英

What is the erasure of a bounded generic type?

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{}

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 to C

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM