My Question: How to overcome an IllegalAccessException
to access the value of an object's field using reflection.
Expansion: I'm trying to learn about reflection to make some of my projects more generic. I'm running into an IllegalAccessException
when trying to call field.getValue(object)
to get the value of that field in that object. I can get the name and type just fine.
If I change the declaration from private
to public
then this works fine. But in an effort to follow the "rules" of encapsulation I don't want to do this. Any help would be greatly appreciated! Thanks!
My Code:
package main; import java.lang.reflect.Field; public class Tester { public static void main(String args[]) throws Exception { new Tester().reflectionTest(); } public void reflectionTest() throws Exception { Person person = new Person("John Doe", "555-123-4567", "Rover"); Field[] fields = person.getClass().getDeclaredFields(); for (Field field : fields) { System.out.println("Field Name: " + field.getName()); System.out.println("Field Type: " + field.getType()); System.out.println("Field Value: " + field.get(person)); //The line above throws: Exception in thread "main" java.lang.IllegalAccessException: Class main.Tester can not access a member of class main.Tester$Person with modifiers "private final" } } public class Person { private final String name; private final String phoneNumber; private final String dogsName; public Person(String name, String phoneNumber, String dogsName) { this.name = name; this.phoneNumber = phoneNumber; this.dogsName = dogsName; } } }
The Output:
run: Field Name: name Field Type: class java.lang.String Exception in thread "main" java.lang.IllegalAccessException: Class main.Tester can not access a member of class main.Tester$Person with modifiers "private final" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:95) at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:261) at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:253) at java.lang.reflect.Field.doSecurityCheck(Field.java:983) at java.lang.reflect.Field.getFieldAccessor(Field.java:927) at java.lang.reflect.Field.get(Field.java:372) at main.Tester.reflectionTest(Tester.java:17) at main.Tester.main(Tester.java:8) Java Result: 1 BUILD SUCCESSFUL (total time: 0 seconds)
If we want to access Private Field and method using Reflection we just need to call setAccessible(true) on the field or method object which you want to access. Class. getDeclaredField(String fieldName) or Class. getDeclaredFields() can be used to get private fields.
The getConstructors() method is used to get the public constructors of the class to which an object belongs. The getMethods() method is used to get the public methods of the class to which an object belongs. We can invoke a method through reflection if we know its name and parameter types.
The set() method of java. lang. reflect. Field is used to set the value of the field represented by this Field object on the specified object argument to the specified new value passed as parameter.
Field used to get the value of the field object. If Field has a primitive type then the value of the field is automatically wrapped in an object. If the field is a static field, the argument of obj is ignored; it may be null Otherwise, the underlying field is an instance field.
Before you get
a private field, you need to call setAccessible(true);
on the corresponding field:
for (Field field : fields) { field.setAccessible(true); // Additional line System.out.println("Field Name: " + field.getName()); System.out.println("Field Type: " + field.getType()); System.out.println("Field Value: " + field.get(person)); }
By default you are not allowed to read non-public fields, but simply invoking field.setAccessible(true);
will allow access. In other words, your code should say
for (Field field : fields) { field.setAccessible(true); // ... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With