0

I would like to know what is the right way to declare Class<...> stateBaseClass, when my goal is to create an instance by using Reflection: state = stateBaseClass.newInstance(); without using cast.

I put some comments in the code below:

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 Answer 1

3

getBaseClass() returns a Class<? extends StateBase> so the result of newInstace can be any subclass of StateBase (depending on the class returned). The compiler cannot be sure that this result is specifically of type State or from another subclass.

To fix this, work with Class<T> and pass this as argument to the constructor of 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;
    }
}

Then in main:

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

state = stateInstDesc.getBaseClass().newInstance(); 
Sign up to request clarification or add additional context in comments.

11 Comments

But there is another way to declare private Class<? extends StateBase> stateBaseClass; to avoid this cast to State? maybe something like private Class<T> stateBaseClass;
It seems like hack-solution. no?
Doesn't seem like a hack to me. That's how the language works.
@Paulo generics is a compile time check, but reflection is a runtime task. At runtime, the JVM doesn't know what generic type you used at compile time so it has to be told what the base class was. It's not elegant and C# can do this for you, but it not considered a hack in Java because this is the best option.
@PeterLawrey i can't use stateBase.getClass(), because stateBase is transient and will be null when i deserialize de StateInstanceDescription
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.