Вопрос рефлексии Java - PullRequest
7 голосов
/ 12 июля 2011

Я работаю над проектом, который использует отражение, чтобы получить поля работающего Java-приложения.

Мне удалось получить поля, но я не могу читать или писать в них. Вот пример, который я нашел в Интернете:

Class aClass = MyObject.class
Field field = aClass.getField("someField");
MyObject objectInstance = new MyObject();
Object value = field.get(objectInstance);
field.set(objetInstance, value);

Проблема в том, что я использую классы из запущенного jar-файла, а классы, которыми я пытаюсь манипулировать, получены из classLoader. Поэтому вместо «MyObject.class» у меня просто «.class». Чтобы получить MyObject, я пытался использовать ClassLoader, но это не сработало.

Если я просто использую '.class':

Object value = field.get(theLoadedClass);

Я получу эту ошибку:

java.lang.IllegalArgumentException: Can not set int field myClass.field to java.lang.Class

Спасибо.

Ответы [ 6 ]

3 голосов
/ 12 июля 2011

Это должно помочь:

Class aClass = myClassLoader.loadClass("MyObject"); // use your class loader and fully qualified class name
Field field = aClass.getField("someField");
// you can not use "MyObject objectInstance = new MyObject()" since its class would be loaded by a different classloader to the one used to obtain "aClass"
// instead, use "newInstance()" method of the class
Object objectInstance = aClass.newInstance();
Object value = field.get(objectInstance);
field.set(objetInstance, value);
2 голосов
/ 12 июля 2011

Из документации: java.lang.IllegalArgumentException выдается:

Если после возможного развертывания новое значение не может быть преобразовано в тип базового поля по тождеству или расширению при преобразовании метод создает исключение IllegalArgumentException.

Это означает, что тип объекта (Объект), который вы пытаетесь установить в поле, не может быть преобразован в фактический тип. Попробуйте не использовать объект там.

Не имеет отношения, глядя на ваш код, я бы изменил

Class aClass = MyObject.class; 

штук до:

Class aClass = Class.forName("fullyQualifiedMyObjectClassName.e.g.com.bla.bla.MyObject");
2 голосов
/ 12 июля 2011

Вам нужен экземпляр соответствующего класса для передачи в методы field.get / set.

Чтобы получить экземпляр из class, вы можете попробовать следующие варианты:

Class<?> clazz = MyObject.class;
// How to call the default constructor from the class:
MyObject myObject1 = clazz.newInstance(); 
// Example of calling a custom constructor from the class:
MyObject myObject2 = clazz.getConstructor(String.class, Integer.class).newInstance("foo", 1); 
0 голосов
/ 12 июля 2011

Это работает?

Class aClass = MyObject.class;
Field field = aClass.getDeclaredField("someField");
field.setAccessible(true);
MyObject objectInstance = new MyObject();
Object value = field.get(objectInstance);
field.set(objectInstance, value);
0 голосов
/ 12 июля 2011

Если вы не знаете тип во время компиляции, используйте:

Class = objectInstance.getClass();

Также, как говорили другие авторы, вы должны знать, какой тип поля, и соответственно использовать правильный тип.

Чтобы определить это время выполнения, используйте Field.getType () и после этого используйте правильный метод получения и установки.

0 голосов
/ 12 июля 2011

Ваши вопросы не очень понятны, но я думаю, что вы спрашиваете, как прочитать значение поля из объекта, используя отражение.

Если вы заглянете в JavaDoc для Field.get, то увидите, что аргументом для Field.get должен быть экземпляр объекта, из которого вы пытаетесь прочитать поле (а не объект Class). Так должно быть что-то вроде:

Object value = field.get(someInstanceOfTheLoadedClass);

Вы, похоже, ошиблись в результате попытки присвоить что-то типа Class полю типа int. Вы должны использовать Field.setInt для установки полей int.

Не имеет значения, получаете ли вы объект Class с помощью .class или с помощью Class.forName.

...