从int到class的映射

时间:2018-06-13 09:21:51

标签: java inria-spoon

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

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

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

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

3 个答案:

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