2011-07-12 4 views
6

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

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

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

Проблема заключается в том, что я использую классы от запущенного файла банки, а классы я пытаюсь манипулировать получаются из 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 

Спасибо.

+0

Что вы подразумеваете под «работающим файлом jar»? Это на вашем пути к классу? – wjans

ответ

0

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

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

Object value = field.get(someInstanceOfTheLoadedClass); 

You erros, кажется, является результатом того, чтобы пытаться присвоить что-то типа класса в поле типа междунар. Вы должны использовать Field.setInt для установки полей int.

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

+0

... или с помощью 'myObject.getClass()'. –

2

Вам нужен экземпляр соответствующего класса для передачи в методы 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

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

Class = objectInstance.getClass(); 

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

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

3

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

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

Из документации: java.lang.IllegalArgumentException брошено:

If, after possible unwrapping, the new value cannot be converted to the type of the underlying field by an identity or widening conversion, the method throws an IllegalArgumentException.

Это означает, что тип объекта (Object), когда вы пытаетесь установить поле для не могут быть преобразованы в фактический тип. Не пытайтесь использовать объект там.

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

Class aClass = MyObject.class; 

часть к:

Class aClass = Class.forName("fullyQualifiedMyObjectClassName.e.g.com.bla.bla.MyObject"); 
0

делает эту работу?

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);