I am not able to get the field value.What I am trying to do is get the Object at runtime. Please let me know where I am going wrong.
Test.class
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException,
IllegalArgumentException, IllegalAccessException {
final Field field = Class.forName("com.logging.EX").getDeclaredField("value");
field.setAccessible(true);
field.get(Class.forName("com.logging.EX"));
}
}
EX.class
public class EX {
private String value;
public EX(){
value="data";
}
/**
* #return the value
*/
public String getValue() {
return value;
}
/**
* #param value
* the value to set
*/
public void setValue(String value) {
this.value = value;
}
}
Something like this...
import java.lang.reflect.Field;
public class Test {
public static void main(String... args) {
try {
Foobar foobar = new Foobar("Peter");
System.out.println("Name: " + foobar.getName());
Class<?> clazz = Class.forName("com.csa.mdm.Foobar");
System.out.println("Class: " + clazz);
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);
String value = (String) field.get(foobar);
System.out.println("Value: " + value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Foobar {
private final String name;
public Foobar(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
Or, you can use the newInstance method of class to get an instance of your object at runtime. You'll still need to set that instance variable first though, otherwise it won't have any value.
E.g.
Class<?> clazz = Class.forName("com.something.Foobar");
Object object = clazz.newInstance();
Or, where it has two parameters in its constructor, String and int for example...
Class<?> clazz = Class.forName("com.something.Foobar");
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
Object obj = constructor.newInstance("Meaning Of Life", 42);
Or you can interrogate it for its constructors at runtime using clazz.getConstructors()
NB I deliberately omitted the casting of the object created here to the kind expected, as that would defeat the point of the reflection, as you'd already be aware of the class if you do that, which would negate the need for reflection in the first place.
You can create instance from class object and that can be used in field get value.
Class modelClass = Class.forName("com.gati.stackoverflow.EX");
final Field field = modelClass.getDeclaredField("value");
field.setAccessible(true);
Object modelInstance=modelClass.newInstance();
field.get(modelInstance);
So, have got the below answer. It is working fine for now. Not sure whether this is the best one to follow.
Your Test class :
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException,
IllegalArgumentException, IllegalAccessException, InstantiationException {
Field[] fields = Class.forName("com.logging.EX").newInstance().getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
System.out.println(field.getName() + " : " + field.get(Class.forName("com.logging.EX").newInstance()));
}
}
}
I'm extracting all the fields in to an array by invoking the instance of com.logging.EX and then loops through all the fields and extracts the name and the value the field holds. Haven't hardcoded any field name here.
There are few security caveats with mine as I've accessed the variable with private access modifier but that always exists with reflection. Just a disclaimer!
Hope this helps!
You need the EX isntance on field.get().
final Field field = Class.forName("com.logging.EX").getDeclaredField("value");
field.setAccessible(true);
field.get(new EX());
Related
I had a class:
class A {
public final Integer orgId;
}
I replaced it with the record in Java 17:
record A (Integer orgId) {
}
Also, I had a code that did a validation via reflection that is working with the regular class, but doesn't work with the Records:
Field[] fields = obj.getClass().getFields(); //getting empty array here for the record
for (Field field : fields) {
}
What would be the correct way to get the Record object fields and its values via reflection in Java 17?
You can use the following method:
RecordComponent[] getRecordComponents()
You can retrieve name, type, generic type, annotations, and its accessor method from RecordComponent.
Point.java:
record Point(int x, int y) { }
RecordDemo.java:
import java.lang.reflect.RecordComponent;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class RecordDemo {
public static void main(String args[]) throws InvocationTargetException, IllegalAccessException {
Point point = new Point(10,20);
RecordComponent[] rc = Point.class.getRecordComponents();
System.out.println(rc[0].getAccessor().invoke(point));
}
}
Output:
10
Alternatively,
import java.lang.reflect.RecordComponent;
import java.lang.reflect.Field;
public class RecordDemo {
public static void main(String args[])
throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException {
Point point = new Point(10, 20);
RecordComponent[] rc = Point.class.getRecordComponents();
Field field = Point.class.getDeclaredField(rc[0].getAccessor().getName());
field.setAccessible(true);
System.out.println(field.get(point));
}
}
Your class and record aren't equivalent: records have private fields.
Class#getFields() returns public fields only.
You could use Class#getDeclaredFields() instead.
I have 2 classes: Father and Child
public class Father implements Serializable, JSONInterface {
private String a_field;
//setter and getter here
}
public class Child extends Father {
//empty class
}
With reflection I want to set a_field in Child class:
Class<?> clazz = Class.forName("Child");
Object cc = clazz.newInstance();
Field f1 = cc.getClass().getField("a_field");
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc.getClass());
System.out.println("field: " + str1);
but I have an exception:
Exception in thread "main" java.lang.NoSuchFieldException: a_field
But if I try:
Child child = new Child();
child.setA_field("123");
it works.
Using setter method I have same problem:
method = cc.getClass().getMethod("setA_field");
method.invoke(cc, new Object[] { "aaaaaaaaaaaaaa" });
To access a private field you need to set Field::setAccessible to true. You can pull the field off the super class. This code works:
Class<?> clazz = Child.class;
Object cc = clazz.newInstance();
Field f1 = cc.getClass().getSuperclass().getDeclaredField("a_field");
f1.setAccessible(true);
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc);
System.out.println("field: " + str1);
Using FieldUtils from the Apache Commons Lang 3:
FieldUtils.writeField(childInstance, "a_field", "Hello", true);
The true forces it to set, even if the field is private.
Kotlin verison
Get private variable using below extension functions
fun <T : Any> T.getPrivateProperty(variableName: String): Any? {
return javaClass.getDeclaredField(variableName).let { field ->
field.isAccessible = true
return#let field.get(this)
}
}
Set private variable value get the variable
fun <T : Any> T.setAndReturnPrivateProperty(variableName: String, data: Any): Any? {
return javaClass.getDeclaredField(variableName).let { field ->
field.isAccessible = true
field.set(this, data)
return#let field.get(this)
}
}
Get variable use:
val bool = <your_class_object>.getPrivateProperty("your_variable") as String
Set and get variable use:
val bool = <your_class_object>.setAndReturnPrivateProperty("your_variable", true) as Boolean
val str = <your_class_object>.setAndReturnPrivateProperty("your_variable", "Hello") as String
Java version
public class RefUtil {
public static Field setFieldValue(Object object, String fieldName, Object valueTobeSet) throws NoSuchFieldException, IllegalAccessException {
Field field = getField(object.getClass(), fieldName);
field.setAccessible(true);
field.set(object, valueTobeSet);
return field;
}
public static Object getPrivateFieldValue(Object object, String fieldName) throws NoSuchFieldException, IllegalAccessException {
Field field = getField(object.getClass(), fieldName);
field.setAccessible(true);
return field.get(object);
}
private static Field getField(Class mClass, String fieldName) throws NoSuchFieldException {
try {
return mClass.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
Class superClass = mClass.getSuperclass();
if (superClass == null) {
throw e;
} else {
return getField(superClass, fieldName);
}
}
}
}
Set private value use
RefUtil.setFieldValue(<your_class_object>, "your_variableName", newValue);
Get private value use
Object value = RefUtil.getPrivateFieldValue(<your_class_object>, "your_variableName");
This one can access private fields as well without having to do anything
import org.apache.commons.lang3.reflect.FieldUtils;
Object value = FieldUtils.readField(entity, fieldName, true);
As per the Javadoc of Class.getField (emphasis mine):
Returns a Field object that reflects the specified public member field of the class or interface represented by this Class object.
This method only returns public fields. Since a_field is private, it won't be found.
Here's a working code:
public class Main {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("Child");
Object cc = clazz.newInstance();
Field f1 = cc.getClass().getField("a_field");
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc);
System.out.println("field: " + str1);
}
}
class Father implements Serializable {
public String a_field;
}
class Child extends Father {
//empty class
}
Note that I also changed your line String str1 = (String) f1.get(cc.getClass()); to String str1 = (String) f1.get(cc); because you need to give the object of the field, not the class.
If you want to keep your field private, then you need to retrieve the getter / setter method and invoke those instead. The code you have given does not work because, to get a method, you also need to specify it's arguments, so
cc.getClass().getMethod("setA_field");
must be
cc.getClass().getMethod("setA_field", String.class);
Here's a working code:
public class Main {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("Child");
Object cc = clazz.newInstance();
cc.getClass().getMethod("setA_field", String.class).invoke(cc, "aaaaaaaaaaaaaa");
String str1 = (String) cc.getClass().getMethod("getA_field").invoke(cc);
System.out.println("field: " + str1);
}
}
class Father implements Serializable {
private String a_field;
public String getA_field() {
return a_field;
}
public void setA_field(String a_field) {
this.a_field = a_field;
}
}
class Child extends Father {
//empty class
}
I have 2 classes: Father and Child
public class Father implements Serializable, JSONInterface {
private String a_field;
//setter and getter here
}
public class Child extends Father {
//empty class
}
With reflection I want to set a_field in Child class:
Class<?> clazz = Class.forName("Child");
Object cc = clazz.newInstance();
Field f1 = cc.getClass().getField("a_field");
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc.getClass());
System.out.println("field: " + str1);
but I have an exception:
Exception in thread "main" java.lang.NoSuchFieldException: a_field
But if I try:
Child child = new Child();
child.setA_field("123");
it works.
Using setter method I have same problem:
method = cc.getClass().getMethod("setA_field");
method.invoke(cc, new Object[] { "aaaaaaaaaaaaaa" });
To access a private field you need to set Field::setAccessible to true. You can pull the field off the super class. This code works:
Class<?> clazz = Child.class;
Object cc = clazz.newInstance();
Field f1 = cc.getClass().getSuperclass().getDeclaredField("a_field");
f1.setAccessible(true);
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc);
System.out.println("field: " + str1);
Using FieldUtils from the Apache Commons Lang 3:
FieldUtils.writeField(childInstance, "a_field", "Hello", true);
The true forces it to set, even if the field is private.
Kotlin verison
Get private variable using below extension functions
fun <T : Any> T.getPrivateProperty(variableName: String): Any? {
return javaClass.getDeclaredField(variableName).let { field ->
field.isAccessible = true
return#let field.get(this)
}
}
Set private variable value get the variable
fun <T : Any> T.setAndReturnPrivateProperty(variableName: String, data: Any): Any? {
return javaClass.getDeclaredField(variableName).let { field ->
field.isAccessible = true
field.set(this, data)
return#let field.get(this)
}
}
Get variable use:
val bool = <your_class_object>.getPrivateProperty("your_variable") as String
Set and get variable use:
val bool = <your_class_object>.setAndReturnPrivateProperty("your_variable", true) as Boolean
val str = <your_class_object>.setAndReturnPrivateProperty("your_variable", "Hello") as String
Java version
public class RefUtil {
public static Field setFieldValue(Object object, String fieldName, Object valueTobeSet) throws NoSuchFieldException, IllegalAccessException {
Field field = getField(object.getClass(), fieldName);
field.setAccessible(true);
field.set(object, valueTobeSet);
return field;
}
public static Object getPrivateFieldValue(Object object, String fieldName) throws NoSuchFieldException, IllegalAccessException {
Field field = getField(object.getClass(), fieldName);
field.setAccessible(true);
return field.get(object);
}
private static Field getField(Class mClass, String fieldName) throws NoSuchFieldException {
try {
return mClass.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
Class superClass = mClass.getSuperclass();
if (superClass == null) {
throw e;
} else {
return getField(superClass, fieldName);
}
}
}
}
Set private value use
RefUtil.setFieldValue(<your_class_object>, "your_variableName", newValue);
Get private value use
Object value = RefUtil.getPrivateFieldValue(<your_class_object>, "your_variableName");
This one can access private fields as well without having to do anything
import org.apache.commons.lang3.reflect.FieldUtils;
Object value = FieldUtils.readField(entity, fieldName, true);
As per the Javadoc of Class.getField (emphasis mine):
Returns a Field object that reflects the specified public member field of the class or interface represented by this Class object.
This method only returns public fields. Since a_field is private, it won't be found.
Here's a working code:
public class Main {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("Child");
Object cc = clazz.newInstance();
Field f1 = cc.getClass().getField("a_field");
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc);
System.out.println("field: " + str1);
}
}
class Father implements Serializable {
public String a_field;
}
class Child extends Father {
//empty class
}
Note that I also changed your line String str1 = (String) f1.get(cc.getClass()); to String str1 = (String) f1.get(cc); because you need to give the object of the field, not the class.
If you want to keep your field private, then you need to retrieve the getter / setter method and invoke those instead. The code you have given does not work because, to get a method, you also need to specify it's arguments, so
cc.getClass().getMethod("setA_field");
must be
cc.getClass().getMethod("setA_field", String.class);
Here's a working code:
public class Main {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("Child");
Object cc = clazz.newInstance();
cc.getClass().getMethod("setA_field", String.class).invoke(cc, "aaaaaaaaaaaaaa");
String str1 = (String) cc.getClass().getMethod("getA_field").invoke(cc);
System.out.println("field: " + str1);
}
}
class Father implements Serializable {
private String a_field;
public String getA_field() {
return a_field;
}
public void setA_field(String a_field) {
this.a_field = a_field;
}
}
class Child extends Father {
//empty class
}
Scenario
I have a list of strings which resembles the names of class variables of a a class. So now i have to set values to those variables using the list.
Example
class Abc {
private String name;
private String Id;
private String sal;
}
public static void main(String args[]){
Map<String,String> variablesMap = new HashMap<String,String>();
variablesMap.add("name","Joshi");
variablesMap.add("id","101");
/*Here i want to write the code to set the values for those variables*/
}
Tried
Class ABC contains all getters and setters.
Using java.lang.Field class i can get the list of variables by ABC.class.getDeclaredFileds(). But after that how do i set the values for those.
You can get a Field for your given name via Field field = getClass().getDeclaredField(name);
Then have a look at the Java Docs: Field Documentation
There you have multiple options to set the value for your variable according to the data type.
Have a look at this example: EDIT: updated to suit your exact question
import java.lang.reflect.Field;
import java.util.Map;
import java.util.HashMap;
public class FieldTest {
String name;
String id;
public static void main(String[] args) {
new FieldTest();
}
public FieldTest() {
Map<String,String> variablesMap = new HashMap<String,String>();
variablesMap.put("name","Joshi");
variablesMap.put("id","101");
for (Map.Entry<String, String> entry : variablesMap.entrySet())
{
try {
test(entry.getKey(),entry.getValue());
}
catch(NoSuchFieldException ex) {
ex.printStackTrace();
}
catch(IllegalAccessException e) {
e.printStackTrace();
}
}
System.out.println(name);
System.out.println(id);
}
private void test(String name, String value) throws NoSuchFieldException, IllegalAccessException {
Field field = getClass().getDeclaredField(name);
field.set(this,value);
}
}
You need to use reflection for this.
say for variable 'name' you have a method getName() in class ABC.
so,
create a method name by iterating your variables map.
then get a method name in string,
String nameMethod = "getName";
Object obj=null;
try
{
method = getClass().getMethod(nameMethod);
obj= method.invoke(this);//if blank then method return null for integer and date column
}
catch(NoSuchMethodException e) {
}
you can not use this snippet as it is, you need to make some modifications
You have to tell the Field which instance to set the values of:
ABC abc = new ABC();
for (Map.Entry<String, String> entry : variablesMap.entrySet())
ABC.class.getDeclaredField(entry.getKey()).set(abc, entry.getValue());
You need to use reflection to set the value of your fields.
One option is to use the set() method of a Field:
getClass().getDeclaredField(myFieldName).set(myObject, myValue);
If you want to use the setter method to set the value, you need to generate the name of the method. And set the value using invoke():
String methodName = "set" + myFieldName.subString(0, 1).toUpperCase() + myFieldName.subString(1);
Method method = getClass().getMethod(methodName, String.class);
method.invoke(myObject, myValue);
//abc is instance of class ABC
BeanInfo info = Introspector.getBeanInfo(abc.getClass(),Object.class);
PropertyDescriptor[] props1 = info.getPropertyDescriptors();
for (PropertyDescriptor pd : props1) {
String name = pd.getName();
String arg1 = variablesMap.get(name);
Method setter = pd.getWriteMethod();
setter.invoke(abc, arg1);
}
Assuming I have an object and I took it fields:
Field[] fields = obj.getFields();
Now I'm iterating through each one and would like to print their members if it's some kind of class, otherwise just use field.get(obj) in case it's a string, int or anything that this command will print its value, not just the reference pointer.
How can I detect it?
You can get, without instantiation required, the Type of each field of a class like this:
public class GetFieldType {
public static void main (String [] args) {
Field [] fields = Hello.class.getFields();
for (Field field: fields) {
System.out.println(field.getGenericType());
}
}
public static class Hello {
public ByeBye bye;
public String message;
public Integer b;
...
}
}
You can use instanceof to tell the objects apart.
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
Object[] objects = new Object[4];
objects[0] = new Integer(2);
objects[1] = "StringTest";
objects[2] = new BigDecimal(2.00d);
for (Object obj : objects) {
if (obj != null) {
if (obj instanceof BigDecimal) {
System.out.println("bigdecimal found " + obj);
} else if (obj instanceof String) {
System.out.println("String found " + obj);
} else {
System.out.println("Integer found " + obj);
}
}
else{
System.out.println("object is null");
}
}
}
If you need to test if an object is from your project, you can look at the package name and compare it to your project's package name.
You can either do this on the declared type of the field or on the runtime type of the field contents. The snippet below demonstrates the latter approach:
SomeClass foo = new SomeClass();
for (Field f : foo.getClass().getDeclaredFields()) {
boolean wasAccessible = f.isAccessible();
try {
f.setAccessible(true);
Object object = f.get(foo);
if (object != null) {
if (object.getClass().getPackage().getName()
.startsWith("your.project.package")) {
// one of yours
}
} else {
// handle a null value
}
} finally {
f.setAccessible(wasAccessible);
}
}
Do remember that obj.getFields(); only returns publicly-accessible fields. You may want to consider getDeclaredFields() as I've done above. If you stick with getFields(), you can omit the accessibility code in the above example.
With a bit of work, you could distinguish your classes by the classloader that loaded them. Take a look at this:
Find where java class is loaded from
Though this could help, it's not going to be the silver bullet for your problem, mainly because:
primitives (byte, short, char, int, long, float, double, and boolean) are not classes.
the architecture of classloaders is different in different app servers.
the same class could be loaded many times by different classloaders.
what I understood is you what to go recursive in object hierarchy and get values of primitives
public class ParentMostClass {
int a = 5;
OtherClass other = new OtherClass();
public static void main(String[] args) throws IllegalArgumentException,
IllegalAccessException {
ParentMostClass ref = new ParentMostClass();
printFiledValues(ref);
}
public static void printFiledValues(Object obj)
throws IllegalArgumentException, IllegalAccessException {
Class<? extends Object> calzz = obj.getClass();
Field[] fileds = obj.getClass().getDeclaredFields();
for (Field field : fileds) {
Object member = field.get(obj);
// you need to handle all primitive, they are few
if (member instanceof String || member instanceof Number) {
System.out.println(calzz + "->" + field.getName() + " : "
+ member);
} else {
printFiledValues(member);
}
}
}
}
public class OtherClass {
int b=10;
}
I got output as
class com.example.ParentMostClass->a : 5
class com.example.OtherClass->b : 10