【问题标题】:How can I dynamically create an instance of a class in java?如何在java中动态创建类的实例?
【发布时间】:2020-02-09 12:38:51
【问题描述】:

我想动态创建一个对象。

我有以下结构: 1个抽象类和几个继承自抽象类的类

abstract public class A {..}


public class B extends A{..}
public class C extends A{..}

我有一个配置文件,我想在其中添加一个类名,以便能够控制应该使用哪个类。

# config class name
 classname = B

我尝试了以下方法,但在这里我遇到了我必须转换结果的问题 而且我现在不知道如何动态地做到这一点

public class TestClass {

  public A instB;

  public void getInstance(){
    this.instB = Class.forName("B") /*here i put later the config value classname*/
    .getConstructor(String.class)
    .newInstance(new Object[]{"test"});   // <--- How to cast this dynamicly to a class in the config?
  }
}

如何动态创建类的实例?

【问题讨论】:

  • 我不确定到底是什么让您感到困惑。您使用newInstance 调用构造函数,提供您的参数,例如newInstance("test"),然后您必须手动转换,例如(A) Class.forName(...)...
  • 如果你坚持强制转换为子类:首先,获取对象。然后使用“instance of”检查类型并进行强制转换。
  • 请注意,如果B 扩展Ainstanceof 已过时。
  • @Zabuza 这里的“过时”是什么意思?
  • 最好在运行构造函数之前使用isAssignableFrom 测试加载的类,而不是使用instanceof,因为如果构造函数不是合适的类,可能会产生不必要的副作用.

标签: java casting


【解决方案1】:

只需将其转换为 A:

instB = (A)Class....newInstance(...);

您不需要知道确切的类别。

【讨论】:

  • 不是那种情况下的实例类型A吗?我总是需要我在配置中定义的类的实例,因为它可能还有其他方法和成员
  • 不,真正的类型不是A,它是扩展A的某个类。如果你写Object o = "string",o的真正类型是String,而不是Object。 声明的类型和实际的类型是有区别的。
【解决方案2】:

我不明白为什么你真的需要使用 reflection。我建议使用简单的策略模式,例如:

策略.java

public interface Strategy {
    void doWork();
}

StrategyA.java

public class StrategyA implements Strategy {
    @Override
    public void doWork() {
    }
}

策略 B.java

public class StrategyB implements Strategy {
    @Override
    public void doWork() {
    }
}

Main.java

public class Main {

    public static void main(String[] args) {
        // read the option from a config file
        String option = "B";
        Strategy strategy = createStrategy(option);

        // create a context with the strategy
        MyContext context = new MyContext(strategy);
        context.doWork();

        // config has changed dynamically, change the strategy
        context.useStrategy(new StrategyA());
        context.doWork();
    }

    public static Strategy createStrategy(String strategy) {

        if (strategy.equals("A")) {
            return new StrategyA();
        }

        return new StrategyB();
    }
}

MyContext.java

public class MyContext {
    Strategy strategy;

    public MyContext(Strategy strategy) {
        this.strategy = strategy;
    }

    public void useStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public void doWork() {
        strategy.doWork();
    }
}

【讨论】:

  • 该解决方案可以工作,但每当我有一个新的 A 子类时,我总是必须扩展此代码。我想避免这种情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 1970-01-01
相关资源
最近更新 更多