Карта от int до класса

Я хочу создавать объекты разных классов на основе пользовательского ввода, т.е. пользователь скажет, какой объект класса создать. У меня есть что-то вроде этого:

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 ответа

Решение

Другое решение, которое вы можете рассмотреть, заключается в следующем:

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> объект может рассматриваться как объектное представление соответствующего файла.class (технически некорректно, но для простоты мы предполагаем, что так оно и есть). Что значит <? extends Processor> значит в бетоне? Это означает, что карта будет разрешать только значения классов, которые являются реализацией или подтипом Processor, Это устраняет нить ClassCastException потому что, если мы можем хранить только классы, которые расширяют Processor, мы можем получить только те классы, которые могут быть преобразованы в 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 -> 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;
        }
    }
}
Другие вопросы по тегам