9

I am working on a project that uses reflection to get the fields of a running java application.

I managed to get the fields, but I can not read or write to them. This is an example I found on the web:

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

The problem is that I use classes from a running jar file, and the classes I try to manipulate are obtained from the classLoader. So instead of 'MyObject.class' I just have the '.class'. To get the 'MyObject' I tried to use a ClassLoader but that did not work.

If I just use '.class':

Object value = field.get(theLoadedClass);

I will get this error:

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

Thanks.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
Natan Griefwell
  • 91
  • 1
  • 1
  • 4

6 Answers6

5

This should help:

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);
JB-
  • 2,615
  • 18
  • 17
2

You need an instance of the appropriate class to pass into the field.get/set methods.

To get an instance from a class you can try these options:

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); 
Bohemian
  • 412,405
  • 93
  • 575
  • 722
2

From the documentation: java.lang.IllegalArgumentException is thrown:

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.

This means the object type (Object) you attempt to set the field to cannot be converted to the actual type. Try not using an Object there.

Unrelated, looking at your code I would change the

Class aClass = MyObject.class; 

piece to:

Class aClass = Class.forName("fullyQualifiedMyObjectClassName.e.g.com.bla.bla.MyObject");
Nikola Yovchev
  • 9,498
  • 4
  • 46
  • 72
0

Your questions is not very clear, but I think you are asking how to read the value of a field from an object using reflection.

If you look in the JavaDoc of Field.get you will see that the argument to Field.get should be the object instance you are trying to read the field from (not the Class object). So it should be something like:

Object value = field.get(someInstanceOfTheLoadedClass);

You erros seems to be a result of trying to assign something of type Class to a field of type int. You should use Field.setInt to set int fields.

It doesn't matter whether you obtain the Class object by using .class or by using Class.forName.

Mathias Schwarz
  • 7,099
  • 23
  • 28
0

If you do not know the type at compile time use:

Class = objectInstance.getClass();

Also as the other posters said you have to know what type the field is and use the correct type accordingly.

To determine this runtime use Field.getType() and use the correct getter and setter after that.

jontro
  • 10,241
  • 6
  • 46
  • 71
0

Does this work?

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);
M.L.
  • 4,686
  • 1
  • 19
  • 15