从 int 映射到 class

Map from int to class

我想根据用户输入创建不同 class 的对象,即用户会告诉要创建哪个 class 的对象。我有这样的东西:

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]);
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;
    }
}

或者,您可以拥有 Int 的映射 -> 类,然后查询该映射以获得给定输入 Int 对应的 class。例如:

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;
        }
    }
}

谢谢路斯·瑟林。我找到了使用 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);

您可能要考虑的另一种解决方案如下:

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确实存在。当您使用 String 和 Class.forName(...) 时,可能会抛出两个额外的异常。首先是 ClassNotFoundException ,如果 Class.forName() 方法没有找到给定名称的 class 将被抛出。第二个额外的异常是 ClassCastException 如果创建的对象不是 Processor.

的实现或子 class 将被抛出

解释:

我们正在使用一个映射,其中 Integer 作为键,Class<? extends Processor> 作为值。 Class<T> 对象可以被认为是对应的 .class 文件的对象表示(技术上不正确,但为了简单起见,我们假设它是那样的)。 <? extends Processor>具体是什么意思?这意味着映射将只允许 类 的值,它们是 Processor 的实现或子类型。这样做消除了 ClassCastException 的线程,因为如果我们只能存储扩展 Processor 的 classes,我们只能检索 classes,它可以转换为 Processor 而无需任何问题,甚至是一个话题。


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