Java实例化通用类型

时间:2016-09-21 14:23:42

标签: java generics casting

我有一个接受两个参数化类型的类,我希望有一个返回其中一个类型的新实例的方法。这是班级:

public class StateMachine<S extends State, E extends StateObject> {

    // State
    protected ArrayMap<S, E> states;
    protected E currentState;
    protected Entity entity;

    // Bits
    private Builder builder = new Builder();
    private int bitOffset;
    private boolean firstState = false;

    public StateMachine(Entity entity) {
        this.entity = entity;
        states = new ArrayMap<S, E>();
    }

    public E createState(S key) {
        // State identifiers must also be taggable
        assert (key instanceof Tag);
        if (!firstState) {
            firstState = true;
            bitOffset = key.numStates();
        }
        E state = (E) new StateObject(entity);
        state.bitOffset = bitOffset;
        state.bits.set(((Tag) key).getIndex());
        states.put(key, state);
        return state;
    }

    // Remainder omitted....

}

如您所见,我想创建一个状态并根据参数化类型返回其值。目前,我有一个EntityState类,其扩展StateObject并且EntityStateMachine扩展StateMachine,其参数为<StateIdentifier, EntityState>。但是,当我从createState致电EntityStateMachine时,返回的值不是EntityState,而是StateObject

如何确保将返回的值转换为正确的参数化类型?

2 个答案:

答案 0 :(得分:4)

要解决此问题的Java模式是存储Class<E>,并使用其newInstance方法,如下所示:

// Class<E> object will be used to create new instances
private final Class<E> stateClass;
// Users will pass the class to StateMachine's constructor
public StateMachine(Entity entity, Class<E> stateClass) {
    this.entity = entity;
    this.stateClass = stateClass;
    states = new ArrayMap<S, E>();
}

现在您可以按如下方式创建新的状态对象:

E state = stateClass.newInstance(); // Only parameterless constructors are supported
state.setEntity(entity);

答案 1 :(得分:2)

  

如何确保将返回的值转换为正确的参数化类型?

这不是你应该问的问题。真正的问题是,

  

如何创建类型参数的实例?

答案当然是“没办法”。你需要一个解决方法,这些是一些想法:

  1. 传递Class<YourType>的实例,以便可以反射创建实例。
  2. 传递YourType
  3. 对象的工厂
  4. 传递YourType的实例,在其上定义newInstance之类的方法,并将其用作更多相同类型对象的工厂。