Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving the data type for an object using reflection

I have an object initialized like :

Object obj  = new Object(){
  final String type = "java.lang.Integer";
  final Object value = 6;
};

I want to recreate this object as :

 Integer i = 6;

Is there any way I can get the type field of obj object and create a new instance using reflection and feed the value in it?

EDIT : Upon extending this question, I find that if I have the object stored in file and retrieve it from file using Jackson using this :

Reader reader = new Reader();
MyClass[] instances = reader.readValue(fileName);

And MyClass is defined as :

class MyClass{

  List<Object> fields;
  .
  .
  .
}

Now I am iterating the fields and converting them into proper objects using the code :

public static Class<?> getTypeForObject(Object field) {

    Field returnType = null;
    try {
        returnType = field.getClass().getDeclaredField("type");
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    }
    return returnType.getType();
}

public static Object getValueForObject(Object field) {

    Object obj = null;
    try {
        obj = field.getClass().getDeclaredField("value").get(field);
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (SecurityException e) {
        e.printStackTrace();
    }
    return obj;
}

But when I watch the expression field.getClass(), it gives me LinkedHashMap as its class. I am confused why and if it that Object is internally treated as Map what options am I left with if I want to do it with reflection without using an concrete data structures so that everything is generalized.

like image 607
Sourabh Avatar asked Jul 10 '14 07:07

Sourabh


People also ask

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.

How do you inherit fields using reflection?

The only way we have to get only inherited fields is to use the getDeclaredFields() method, as we just did, and filter its results using the Field::getModifiers method. This one returns an int representing the modifiers of the current field. Each possible modifier is assigned a power of two between 2^0 and 2^7.

What is reflection and how does it help to manipulate Java code?

Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them.


3 Answers

Yes, you can. But since the type of obj is an anonymous class extending java.lang.Object, you can't reference its fields (type and value) directly, only via reflection.

Here's the code how you could do it:

    String type = (String) obj.getClass().getDeclaredField("type").get(obj);
    Object value = obj.getClass().getDeclaredField("value").get(obj);

    // Type can be anything, so in order to instantiate it,
    // we have to assume something. We assume it has a constructor
    // which takes only a String value.
    Object recreated = Class.forName(type).getConstructor(String.class)
            .newInstance(value == null ? null : value.toString());
    System.out.println(recreated);
like image 157
icza Avatar answered Nov 03 '22 20:11

icza


Just have a look at new updated code :

Object obj = new Object() {
    final String type = "java.lang.Integer";
    final Object value = 6;
};

public void demo(){

    try {
        Field typeField = obj.getClass().getDeclaredField("type");
        typeField.setAccessible(true);
        String type = typeField.get(obj).toString();
        Field valueField = obj.getClass().getDeclaredField("value");
        valueField.setAccessible(true);
        String value = valueField.get(obj).toString();
        Class intClass = Class.forName(type);
        Constructor intCons = intClass.getConstructor(String.class);
        Integer i = (Integer) intCons.newInstance(value.toString());
        System.out.println(i);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Note : got help from this question.

UPDATE: Now getting the type and value from Object obj.

like image 30
earthmover Avatar answered Nov 03 '22 20:11

earthmover


This will retrieve value of a type field from your object:obj.getClass().getDeclaredField("type").get(obj);.

like image 22
Bananan Avatar answered Nov 03 '22 20:11

Bananan