我想根据用户输入创建不同类的对象,即用户将告诉要创建哪个类的对象。我有这样的事情:
launcher.addProcessor((Processor) new SerializableFieldProcessor(projectKey));
现在我有其他处理器,并希望用户给出一个整数输入,并根据它,创建相应处理器的对象。一种简单的方法是使用开关盒,但后来我将拥有超过50或100个独立的处理器。有没有办法用地图或类似的东西做到这一点?像这样:
Map<int,Processor> mymap;
//initialize mymap;
int x= user_input;
launcher.addProcessor((Processor) new mymap[x]);
答案 0 :(得分:2)
您可能需要考虑的另一个解决方案如下:
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
类型,并且该类确实存在。当您使用字符串和Class.forName(...)
时,可能会抛出另外两个异常。首先是ClassNotFoundException
,如果Class.forName()
方法没有找到给定名称的类,则会抛出ClassCastException
。第二个额外的异常是Processor
,如果创建的对象不是Integer
的实现或子类,将抛出该异常。
<强>解释强>
我们使用的地图以Class<? extends Processor>
为密钥,Class<T>
为我们的值。 <? extends Processor>
对象可以被视为对应的.class文件的对象表示(技术上不正确,但为了简单起见,我们假设它是这样的)。 Processor
具体意味着什么?这意味着地图将仅允许作为实现或类型为ClassCastException
的类的值。这样做会消除Processor
的线程,因为如果我们只能存储扩展Processor的类,那么我们只能检索可以被转换为UIView.appearance().tintColor = myColor
而没有任何问题的类,甚至是一个线程。
注意:我链接了实例化过程,这在生产环境中通常是一个坏主意,但它会大大缩短代码并且无需进一步解释它,因为您使用完全相同的接近你自己的答案。
答案 1 :(得分:1)
谢谢Lews Therin。我找到了一个使用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);
答案 2 :(得分:-1)
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地图 - &gt;然后查询类,然后查询映射以获取给定输入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;
}
}
}