使用反射基于泛型类的getClass创建实例

时间:2015-04-20 17:53:09

标签: java generics reflection

我想知道宣布Class<...> stateBaseClass的正确方法是什么,当我的目标是使用Reflection:state = stateBaseClass.newInstance();而不使用强制转换来创建实例时。

我在下面的代码中添加了一些注释:

abstract class StateBase{} // It is so complex to be serializable.

class State extends StateBase{}

class StateInstanceDescription <T extends StateBase> implements Serializable{ 
    private static final long serialVersionUID = -828114417567233018L;

    transient private T stateBase;

    // what is the right way to declare the line below to void that cast?
    private Class<? extends StateBase> stateBaseClass; 

    public StateInstanceDescription(T base){
        this.stateBase = base;
        stateBaseClass = base.getClass();
    }

    public T getBase() {
        return stateBase;
    }

    public Class<? extends StateBase> getBaseClass() {
        return stateBaseClass;
    }

}

public class Main {
    public static void main(String ... args) throws InstantiationException, IllegalAccessException{
        State state = new State();
        StateInstanceDescription<State> stateInstDesc = new StateInstanceDescription<>(state);

        // ... At some point, I will recreate State after deserialize stateInstDesc.
        // compiler-time error. Compiler is asking for casting it to (State). 
        // There is a way to avoid this cast?
        state = stateInstDesc.getBaseClass().newInstance(); 
    }
}

1 个答案:

答案 0 :(得分:3)

getBaseClass()返回Class<? extends StateBase>,因此newInstace的结果可以是StateBase的任何子类(取决于返回的类)。编译器无法确定此结果是否特定于类型State或来自其他子类。

要解决此问题,请使用Class<T>并将其作为参数传递给StateInstanceDescription的构造函数:

class StateInstanceDescription <T extends StateBase> implements Serializable { 

    transient private T stateBase;

    private Class<T> stateBaseClass; 

    public StateInstanceDescription(T base, Class<T> clazzBase) {
        this.stateBase = base;
        stateBaseClass = clazzBase;
    }

    public T getBase() {
        return stateBase;
    }

    public Class<T> getBaseClass() {
        return stateBaseClass;
    }
}

然后在main

State state = new State();
StateInstanceDescription<State> stateInstDesc = new StateInstanceDescription<>(state, State.class);

state = stateInstDesc.getBaseClass().newInstance();