Reputation: 1303
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.
Upvotes: 5
Views: 11920
Reputation: 4525
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
.
Upvotes: 2
Reputation: 417612
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);
Upvotes: 8
Reputation: 5758
Yes, You can use Class.forName
.
For example, instead of Integer, consider a Person--
public static String getObjectType()
{
return "Person";
}
final String type = getObjectType();
Class.forName(type); //returns the `Person.class`, if Person.class is in classpath if not throws a `ClassNotFoundException`
To create a Person object from the Person.Class you can do something like this -
final Person p = Person.class.getConstructor(Integer.class, String.class).newInstance(age, name);
Upvotes: 1
Reputation: 609
This will retrieve value of a type
field from your object:obj.getClass().getDeclaredField("type").get(obj);
.
Upvotes: 1