我想根据用户输入创建不同类的对象,即用户将告诉要创建哪个类的对象。我有这样的东西:
launcher.addProcessor((Processor) new SerializableFieldProcessor(projectKey));
现在我有其他处理器,并希望用户给出一个整数输入,并在此基础上创建相应处理器的对象。一个简单的方法是使用开关机箱,但稍后我将拥有 50 或 100 多个独立的处理器。有没有办法用地图或类似的东西来做到这一点?像这样:
Map<int,Processor> mymap;
//initialize mymap;
int x= user_input;
launcher.addProcessor((Processor) new mymap[x]);
您可能需要考虑的另一种解决方案如下:
Map<Integer, Class<? extends Processor>> map = new HashMap<>();
// Integer.valueOf(x) used to prevent autoboxin just a matter of opinion.
map.put( Integer.valueOf( 0 ), MyProcessor.class );
Processor chosen = map.get( userIn ).getConstructor( String.class ).newInstance( projectKey );
launcher.addProcessor(chosen);
它基本上是相同的,但区别在于返回的对象属于Processor
类型,并且类确实存在。使用 String 和Class.forName(...)
时,可能会引发两个额外的异常。首先是Class.forName()
方法未找到给定名称的类时将引发的ClassNotFoundException
。第二个附加异常是如果创建的对象不是Processor
的实现或子类,则会抛出ClassCastException
。
解释:
我们使用的地图以Integer
为关键,以Class<? extends Processor>
为价值。可以将Class<T>
对象视为相应.class文件的对象表示形式(技术上不正确,但为了简单起见,我们假设它是这样(。混凝土中的<? extends Processor>
是什么意思?这意味着映射将只允许作为Processor
的实现或子类型的类的值。这样做消除了ClassCastException
的线程,因为如果我们只能存储扩展处理器的类,我们只能检索可以强制转换为Processor
而不会出现任何问题甚至线程的类。
注意:我链接了实例化过程,这在生产环境中通常是一个坏主意,但它大大缩短了代码,无需进一步解释,因为您在自己的答案中使用完全相同的方法。
谢谢卢斯·特林。我找到了使用Java Reflection的解决方案。
Map<Integer,String > rule=new HashMap<Integer, String>();
rule.put(1948,"SerializableFieldProcessor");
Class<?> processor = Class.forName(rule.get(1948));
Constructor<?> cons = processor.getConstructor(String.class);
Object object = cons.newInstance(projectKey);
launcher.addProcessor( (Processor)object);
public class Foo { }
public class Bar { }
private Object userChosenClass(Int userInput) {
if (userInput == 0) {
return new Foo();
} else if (userInput == 1) {
return new Bar();
} else {
return null;
}
}
或者,您可以拥有 Ints -> 类的映射,然后查询映射以获取给定输入 Int 的相应类。例如:
public class UserClassSelector {
private Map<Int, Class> map;
public UserClassSelector() {
map = new Map<Int, Class>();
}
public Void addMapping(Int fromInt, Class toClass) {
map[fromInt] = toClass;
}
public Object instantiateFromMap(Int forInt) {
if (map[forInt] != null) {
return new map[forInt]();
} else {
return null;
}
}
}