Карта от int до класса - PullRequest
0 голосов
/ 13 июня 2018

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

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 голосов
/ 13 июня 2018

Спасибо, Льюс Терин.Я нашел решение, используя 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);
0 голосов
/ 13 июня 2018

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

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, и класс определенно существует.Когда вы используете String и Class.forName(...), есть два дополнительных исключения, которые могут быть выброшены.Сначала ClassNotFoundException, который будет выдан, если метод Class.forName() не нашел класс для данного имени.Второе дополнительное исключение - ClassCastException, которое будет выброшено, если созданный объект не является реализацией или подклассом Processor.


Объяснение:

Мы используем карту с Integer в качестве нашего ключа и Class<? extends Processor> в качестве нашего значения.Объект Class<T> может рассматриваться как объектное представление соответствующего файла .class (технически некорректно, но для простоты мы предполагаем, что так оно и есть).Что означает <? extends Processor> в бетоне?Это означает, что карта будет разрешать только значения классов, которые являются реализацией или подтипом Processor.Это исключает поток ClassCastException, потому что, если мы можем хранить только классы, расширяющие Processor, мы можем извлекать только те классы, которые могут быть преобразованы в Processor без каких-либо проблем или даже из одного потока.


Примечание: Я включил процесс создания экземпляра, который обычно является плохой идеей в продуктивной среде, но он значительно сокращает код, и нет необходимости дополнительно его объяснять, поскольку вы используете точно такой же подходв вашем собственном ответе.

0 голосов
/ 13 июня 2018
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;
        }
    }
}
...