0

我想根据用户输入创建不同类的对象,即用户将告诉创建哪个类的对象。我有这样的事情:

launcher.addProcessor((Processor) new SerializableFieldProcessor(projectKey));

现在我有其他处理器并希望用户提供一个整数输入,并根据它创建相应处理器的对象。一种直接的方法是使用 switch case,但稍后我将拥有超过 50 或 100 个单独的处理器。有没有办法用地图或类似的东西来做到这一点?像这样的东西:

Map<int,Processor> mymap;
//initialize mymap;
int x= user_input;
launcher.addProcessor((Processor) new mymap[x]);
4

3 回答 3

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将抛出 which 。Class.forName()第二个附加异常是ClassCastException如果创建的对象不是Processor.


解释:

我们正在使用以 aInteger作为我们的键和 aClass<? extends Processor>作为我们的值的映射。可以将Class<T>对象视为相应 .class 文件的对象表示(技术上不正确,但为简单起见,我们假设是这样)。<? extends Processor>在混凝土中是什么意思?这意味着地图将只允许作为实现或子类型的类的值Processor。这样做消除了 a 的线程,ClassCastException因为如果我们只能存储扩展 Processor 的类,我们只能检索可以转换为 an 的类,Processor而没有任何问题,甚至是 one 的线程。


注意:我链接了实例化过程,这在生产环境中通常是一个坏主意,但它大大缩短了代码,并且无需进一步解释它,因为您在自己的答案中使用了完全相同的方法。

于 2018-06-13T11:05:33.337 回答
1

谢谢刘易斯·瑟林。我找到了使用 Java 反射的解决方案。

 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);
于 2018-06-13T10:48:05.973 回答
0
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 -> Classes 的映射,然后查询该映射以获取给定输入 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;
        }
    }
}
于 2018-06-13T09:24:44.120 回答