简体   繁体   中英

Inconvertible types; cannot cast 'caputure<? extends IEntity>'to 'java.lang.Class<T>'

There are three class,class IEntity is an abstract class,which is only used for generic.

Class one:

public abstract class IEntity {
}

class two:

public class Config {
    private Class<? extends IEntity> clazz;

    public Class<? extends IEntity> getClazz(){
        return this.clazz;
    }
}

class three:

public class EntityTest<T extends IEntity> {
    private Class<T> clazz;

    public void init(Config config){
       //Here is the wrong report
       // Failed to compile
        this.clazz=config.getClazz();
    }
}

It seems like you have not understood the difference between <? extends IEntity> <? extends IEntity> and <T extends IEntity> .

Let's introduce two subclasses of IEntity , and a constructor for Config for a clearer explanation:

class Entity1 extends IEntity {}
class Entity2 extends IEntity {}

// in Config class
public Config(Class<? extends IEntity> clazz) {
    this.clazz = clazz;
}

At the line this.clazz=config.getClazz(); , you are trying to assign a Class<? extends IEntity> Class<? extends IEntity> to a Class<T> , where T is a subclass of IEntity or IEntity itself. The problem is, we don't know exactly what type of class getClazz returns. It could be Class<Entity1> , or Class<Entity2> . On the other hand, we do know what type we need - Class<T> . How can we make sure that whatever getClazz returns, is the same type of class as Class<T> ? T could be Entity2 but getClazz could return Class<Entity2> , couldn't it?

Here's a concrete example with code:

Config c = new Config(Entity1.class);
// c.config now contains Entity1.class
// the line below will attempt to assign an Entity1.class to a variable of type Class<Entity2>
new EntityTest<Entity2>().init(c);

You should now see why there is an error in init .

One way to make sure that getClazz returns the same type of class as Class<T> is to make Config generic too:

class Config<T extends IEntity> {
    private Class<T> clazz;

    public Class<T> getClazz(){
        return this.clazz;
    }
}

class EntityTest<T extends IEntity> {
    private Class<T> clazz;

    public void init(Config<T> config){
        this.clazz=config.getClazz();
    }
}

<? extend IEntity> <? extend IEntity> indicates that the class must be IEntity or it's subclass. The "T" in your code is just one subclass of IEntity(there can be many subclasses of <? extend IEntity> ), you could not be sure that <? extend IEntity> <? extend IEntity> is same as "T" or is subclass of "T". so the type cast is illegale.

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