Создание объекта данного класса, реализующего интерфейс, и добавление его в список <InterfaceX>с использованием отражения - PullRequest
0 голосов
/ 27 сентября 2019

У меня есть интерфейс «Инструкция», и некоторые инструкции реализуют его (Add, Sub, Mul, Jmp ...), для выполнения этих инструкций я сохраняю их в объекте List и впоследствии вызываю метод execute ().Я читаю эту инструкцию из файла и хочу создать соответствующий класс с помощью чтения строки из файла, но когда я вызываю constructor.newInstance (...), я теряю тип ссылки и не могувызывать методы без instanceofs и грязных приведений (я хочу их избегать).

List<Instruction> res = new ArrayList<>()
String className = "Add";
Class<?> classLoaded = Class.forName("instructions." + className);
Constructor<?> constructor = classLoaded.getConstructors()[0];
Object obj = constructor.newInstance(paramsOfConstructor);
res.add(obj);

Это работает так, как я хочу, чтобы это работало, но я хочу избегать как можно более грязных приведений

Instruction obj = (Instruction) constructor.newInstance(paramsOfConstructor);
res.add(obj);

PD: paramsOfConstructor - это все объекты / примитивы, которые я даю конструктору, я не включаю код для их получения, потому что это будет копирование / вставка примерно из 30 строк.При необходимости я могу также скопировать их.

1 Ответ

0 голосов
/ 27 сентября 2019

Вы можете использовать метод Class.asSubclass(), чтобы изменить Class<?> объект, возвращаемый Class.forName(...), на что-то, с чем вы можете работать.В сочетании с методом getConstructor() (единственный, без s) вы можете создать объект Constructor с нужным вам типом.Код будет выглядеть примерно так:

Class<?> loadedClass = Class.forName("java.lang.Thread");
Class<? extends Runnable> castedClass = loadedClass.asSubclass(Runnable.class);
Class<?>[] constructorArgumentClasses = new Class<?>[] { String.class }; // pick the constructor: new Thread(String)
Constructor<? extends Runnable> c = castedClass.getConstructor(constructorArgumentClasses);
Runnable t = c.newInstance("abc"); // no casting involved here

System.out.println(t);            // Thread[abc,5,main]
System.out.println(t.getClass()); // class java.lang.Thread

Вы должны переписать свой код, который вы используете getConstructor() вместо getConstructors() (вы все равно используете только один), потому что этот метод возвращает Constructor<? extends T> объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...