【问题标题】:Creating an object knowing his class创建一个知道他的类的对象
【发布时间】:2016-02-17 09:34:58
【问题描述】:

我想存储在一个枚举类上,以便稍后我可以实例化这个类。但我不知道我该怎么做。

这是一个例子:

public enum STATE {
 MENU(Menu.class, Color bgColor);
 PLAY(Play.class, Color bgColor);
 ...
 public STATE() {...
 }
}

并且有一种在状态之间改变的方法。 STATE 上的所有类都继承自 AState,例如 (public class Menu extends AState{...})

Astate currentState;
public void changeState(STATE s){
  if(currentState != null) currentState.dispose();
  currentState = ...some code to instantiate the class and assign to this value
  currentState.init();
}

我的想法是有一个枚举来保存每个状态的类,以及一些参数来用不同的值实例化这个类,比如他的 bgColor,但我不知道如何在 Java 中做到这一点。

【问题讨论】:

    标签: java class inheritance


    【解决方案1】:

    我建议在这个枚举中使用抽象工厂方法。

    public enum State {
        MENU {
            public AState createInstance() { return new Menu();}
        },
        PLAY {
            public AState createInstance() { return new Play();}
        };
    
        public abstract AState createInstance();
    }
    

    那么你可以这样做:

    public void changeState(State s){
        if(currentState != null) currentState.dispose();
        currentState = s.createInstance();
    }
    

    我省略了颜色字段,因为不清楚它应该如何使用。如果每个状态的颜色都相同,则可以将其作为附加私有字段添加到枚举中。如果在构造新的AState 实例时使用各种颜色,可以将其作为参数传递给createInstance() 方法。

    如果你使用 Java 8,这个枚举可以用更优雅的方式编写:

    public enum State {
        MENU(Menu::new),
        PLAY(Play::new);
    
        Supplier<AState> stateConstructor;
    
        State(Supplier<AState> constructor) {
            stateConstructor = constructor;
        }
    
        public AState createInstance() {
            return stateConstructor.get();
        }
    }
    

    【讨论】:

      【解决方案2】:

      您不能通过其构造函数初始化 enum 元素,这就是为什么 enum 构造函数可以是 private 或受包保护的原因。

      您上面的public 构造函数将无法编译。

      要将enum 值分配给引用,您可以使用以下成语:

      STATE currentState = STATE.MENU;
      

      【讨论】:

        【解决方案3】:

        你的问题的答案在这里https://stackoverflow.com/a/6094602/1885467

        Astate currentState;
        public void changeState(STATE s){
            if(currentState != null) currentState.dispose();
            Constructor<?> ctor = s.clazz.getConstructor();
            currentState = (Astate)ctor.newInstance();
            currentState.init();
        }
        

        虽然我不知道是否没有更好的方法来解决您在应用程序中遇到的一般问题。

        【讨论】:

          【解决方案4】:

          这里是示例代码。

          public enum SomeEnum {
          
          MENU(SomeState.class, "This is menu");
          
          private Class<? extends State> clazz;
          private String value;
          
          SomeEnum(final Class<? extends State> clazz, final String value){
              this.clazz = clazz;
              this.value = value;
          }
          
          
          public State getState() throws InstantiationException, IllegalAccessException{
              State newInstance = clazz.newInstance();
              newInstance.setSomeValue(value);
              return newInstance;
          }
          }
          

          public class SomeState implements State {
          
          private String value;
          
          @Override
          public void runState() {
              System.out.println("Running with value : " + value);
          }
          
          @Override
          public void setSomeValue(String value) {
              this.value = value;
          
          }
          
          }
          

          public interface State {
          void runState();
          void setSomeValue(String value);
          }
          

          public class Test {
          public static void main(String[] args) throws InstantiationException, IllegalAccessException {
              SomeEnum.MENU.getState().runState();
          }
          }
          

          【讨论】:

            猜你喜欢
            • 2010-09-22
            • 1970-01-01
            • 1970-01-01
            • 2021-09-29
            • 2021-12-15
            • 2016-04-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多