Wednesday, 19 July 2017

Reflection in Java - Field

Reflection in Java class gives a good idea about how class is an entry point to all the Reflection APIs. Once you have Class object you can get information about members of the class fields, constructors, methods.

Member Interface

With in the Reflection hierarchy an interface java.lang.reflect.Member is defined which is implemented by java.lang.reflect.Field, java.lang.reflect.Method, and java.lang.reflect.Constructor. Thus Member is an interface that reflects identifying information about a single member (a field or a method) or a constructor.

This post talks about Field class and the methods it provides in detail. Class fields have a type and a value, the java.lang.reflect.Field class provides methods for accessing type information, field’s modifier and setting and getting values of a field on a given object.

How to get Field object

There are 4 methods for getting fields of the class.

  • getField(String name) - Returns a Field object that reflects the specified public member field of the class or interface represented by this Class object.
  • getFields() - Returns an array containing Field objects reflecting all the accessible public fields of the class or interface represented by this Class object.
  • getDeclaredField(String name) - Returns a Field object that reflects the specified declared field of the class or interface represented by this Class object.
  • getDeclaredFields() - Returns an array of Field objects reflecting all the fields declared by the class or interface represented by this Class object.

So getFields() methods will only return object for public fields where as getDeclaredField() methods will return all the fields.

Example code

In this example generic class ReflectField is used which has few fields with access modifier as public or private.

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

public class ReflectField<T> {
     public String name = "Test";
     private int i = 10;
     public List<Integer> numList;
     public T val;
     
     public static void main(String arg[]){
      try {
       Class<?> c = Class.forName("org.netjs.prog.ReflectField");
       try {
        Field f = c.getField("name");
        System.out.println("Name field " + f.getName());
        
        Field[] fields = c.getFields();
        System.out.println("All Fields - " + Arrays.toString(fields));
        
        fields = c.getDeclaredFields();
        
        System.out.println("Declared Fields - " + Arrays.toString(fields));
       } catch (NoSuchFieldException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
       } catch (SecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
       }
       
      }catch (ClassNotFoundException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
    }
}

Output

Name field name

All Fields - [public java.lang.String org.netjs.prog.ReflectField.name, public java.util.List org.netjs.prog.ReflectField.numList, 
public java.lang.Object org.netjs.prog.ReflectField.val]

Declared Fields - [public java.lang.String org.netjs.prog.ReflectField.name, private int org.netjs.prog.ReflectField.i, 
public java.util.List org.netjs.prog.ReflectField.numList, public java.lang.Object org.netjs.prog.ReflectField.val]

You can see here getFields() return array of all public fields in the class where as getDeclaredFields() return all the fields (field i is having access modifier as private).

Getting the field type

If you want to know the types of fields in any class reflectively you can do it using the methods getType() and getGenericType() methods.

Example code

Class<?> c = Class.forName("org.netjs.prog.ReflectField");
fields = c.getDeclaredFields();
for(Field field : fields){
    System.out.println("Field name - " + field.getName() + " has Field Type " + field.getType());
    System.out.println("Field name - " + field.getName() + " has Generic Field Type " + field.getGenericType());
}

Output

Field name - name has Field Type class java.lang.String
Field name - name has Generic Field Type class java.lang.String
Field name - i has Field Type int
Field name - i has Generic Field Type int
Field name - numList has Field Type interface java.util.List
Field name - numList has Generic Field Type java.util.List<java.lang.Integer>
Field name - val has Field Type class java.lang.Object
Field name - val has Generic Field Type T

Here notice that the type for the field val is displayed as java.lang.Object because generics are implemented via type erasure which removes all information regarding generic types during compilation. Thus T is replaced by the upper bound of the type variable, in this case, java.lang.Object.

Getting field modifiers

You can get the field modifiers by using the getModifiers() method. This method returns the Java language modifiers for the field represented by this Field object, as an integer. The Modifier class should be used to decode the modifiers.

Example code

Class<?> c = Class.forName("org.netjs.prog.ReflectField");
fields = c.getDeclaredFields();
for(Field field : fields){     
    System.out.println("Field name - " + field.getName() + " has modifier " + Modifier.toString(field.getModifiers()));
}

Output

Field name - name has modifier public
Field name - i has modifier private
Field name - numList has modifier public
Field name - val has modifier public

Getting and Setting Field Values

If you have an object of a class, using reflection you can set the values of fields in that class. This is typically done only in special circumstances when setting the values in the usual way is not possible. Because such access usually violates the design intentions of the class, it should be used with the utmost discretion.

Example code

Given a public field name which is of type String here the new value is set to the field name.

public String name = "Test";
Class<?> c = Class.forName("org.netjs.prog.ReflectField");
ReflectField rf = new ReflectField();
Field f = c.getField("name");
// getting the field value
System.out.println("Value of field name " + f.get(rf));
// setting the new field value
f.set(rf, "New Value");
System.out.println("Value of field name " + rf.name);

Output

Value of field name Test
Value of field name New Value

That's all for this topic Reflection in Java - Field. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Reflection in Java
  2. Reflection in Java - Class
  3. Invoking getters and setters using Reflection - Java Program
  4. Object cloning in java
  5. Serialization in Java

You may also like -

>>>Go to Java advance topics page

1 comment:

  1. very very amazing explaintion....many things gather about yourself...yes realy i enjoy it
    SEO Company in India

    ReplyDelete