提问人:Dominic Miller 提问时间:9/22/2023 更新时间:9/26/2023 访问量:112
如何在 Java 中初始化一个类,而我要初始化的类会因变量而异?
How do I initialize a class in Java, while the class I want to initialize will vary based on a variable?
问:
我正在尝试制作一个终端程序,该程序将根据用户的输入初始化一个类。有没有办法使用 String 变量初始化特定类,而不会用语句弄乱我的程序?下面是我尝试执行的操作的示例:if
终端:
Which program would you like to run? Please type in lower case.
- Room designer
- Etc.
>
法典:
String answer = input.nextLine();
[answer] programToRun = new [answer]();
有没有办法做到这一点?我知道 Python 中有一种方法使用字典,所以我相信有一种方法,只是我无法找到它。Globals
答:
2赞
ControlAltDel
9/22/2023
#1
执行此操作的方法是使用 Factory 模式
interface Factory<T> {
T createInstance(String param);
}
public class FactoryManager {
private Map<String,Factory> factories;
public void registerFactory(String type, Factory f) ... // add the key/pair to the factories map
public Object createInstance(String s) ... // match the string to a Factory in the factories Map and call createInstance on it
}
如果您对此有任何疑问,请告诉我
--编辑--
例:
public class Car {
private make = null;
public Car() {};
public Car(String make) {
this.Car();
this.make = make;
}
}
public class CarFactory implements Factory<Car> {
public Car createInstance(String s) {
return new Car(s);
}
}
public class Bus {
private make = null;
public Bus() {};
public Bus(String make) {
this.Bus();
this.make = make;
}
}
public class BusFactory implements Factory<Bus> {
public Car createInstance(String s) {
return new Bus(s);
}
}
public class MyFactoryManager extends FactoryManager {
public MyFactoryManager() {
//All this actually should be in the base class FactoryManager so it doesn't need to be implemented in each FactoryManager.
factories = new HashMap<String, Factory>();
public Object createInstance(String s) { // This could be expanded with another parameter to be passed to the factory for object initialization.
return factories.get(s).createInstance();
}
}
}
FactoryManager fm = new MyFactoryManager();
fm.reqisterFactory("car", new CarFactory());
fm.reqisterFactory("bar", new BusFactory());
Object car = fm.createInstance("car");
Object bus = fm.createInstance("bus");
System.out.println("Car is a " + car.getClass());
System.out.println("Bus is a " + bus.getClass());
评论
0赞
Dominic Miller
9/22/2023
我不熟悉工厂模式。不幸的是,我不是最流利的 Java。您能提供更多信息吗?
0赞
ControlAltDel
9/22/2023
@DominicMiller baeldung.com/java-factory-pattern
0赞
Dominic Miller
9/22/2023
是方法吗?在这种情况下,我是否应该扩展它并使用该地图将其全部连接在一起?我有点了解,但我不确定如何整合它。@ControlAltDelregisterFactory
0赞
ControlAltDel
9/22/2023
@DominicMiller是的,registerFactory 是一个方法。我不确定你所说的“扩展它”是什么意思,但如果你的意思是填写方法,以便它将类型/工厂对添加到地图中并使用地图来履行,那么是的createInstance
FactoryManager
0赞
Dominic Miller
9/26/2023
对不起,我知道我很久以前就已经选择了这个作为答案,我知道它会起作用,但我就是无法实现它。你认为我可以举一个例子来解释事情吗?感谢您的耐心等待。@ControlAltDel
0赞
Fabian Witte
9/22/2023
#2
您可以使用以下代码从字符串创建类的实例,使用其 no-args 构造函数(如果不存在此类构造函数,则崩溃):
package plugins;
public class ClassName {
@Override
public String toString() {
return "Works as expected!";
}
}
public class ClassByNameTest {
@Test
void createInstance() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
String className = "plugins.ClassName";
Object instance = Class.forName(className).getConstructor().newInstance();
assert a.getClass().getName().equals(className);
System.out.println(instance.toString());
}
}
遵循某种约定,例如实现一个公共接口,你可以调用一个入口点方法来动态运行任意行为。
编辑: 尽管这在技术上没有问题,但使用工厂模式的 ControlAltDels 想法是解决这个问题的更好方法,特别是因为它将用户输入与实际类名分离。
0赞
Reilas
9/22/2023
#3
"...有没有办法使用 String 变量初始化特定类,而不会用
if
语句弄乱我的程序?..."
您可以使用反射框架通过 String 值实例化类。
需要提供完全限定的名称。
Class<?> c = Class.forName("java.lang.String");
Object instance = c.getDeclaredConstructor().newInstance();
上一个:对象名在 C++ 中包含什么?
下一个:如何使用购物车产品对象构建购物车
评论
new A()
new B()