Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access a field's value in an object using reflection

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) 
like image 828
kentcdodds Avatar asked Oct 08 '12 15:10

kentcdodds


People also ask

How do you access a private field using a reflection?

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.

How do you find the object of a class using reflection?

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.

Which method Changes value of some field?

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.

What is a field value in Java?

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.


2 Answers

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)); } 
like image 112
Michael Berry Avatar answered Oct 06 '22 14:10

Michael Berry


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);   // ... } 
like image 31
Marko Topolnik Avatar answered Oct 06 '22 14:10

Marko Topolnik