Why the value is null for the variable2 , if I instantiate the class using Reflection API?
Where, the value of Variable1 is returned correctly as per the set and here I instantiated the object normally.
How can I obtain the value of variable2 using ReflectionAPI?
package com.OP.app;
public class Bean {
private String variable1;
private String variable2;
public String getVariable1() {
return variable1;
}
public void setVariable1(String variable1) {
this.variable1 = variable1;
}
public String getVariable2() {
return variable2;
}
public void setVariable2(String variable2) {
this.variable2 = variable2;
}
}
package com.OP.app;
import java.lang.reflect.Method;
public class ObjectCall {
public static void main(String []args){
Bean beanobject = new Bean();
beanobject.setVariable1("Ram");
beanobject.setVariable2("Rakesh");
System.out.println(beanobject.getVariable1());
String path = "com.OP.app.Bean";
Class<?> newClass;
try {
newClass = Class.forName(path);
Object obj = newClass.newInstance();
String getMethod = "getVariable2";
Method getNameMethod = obj.getClass().getMethod(getMethod);
String name = (String) getNameMethod.invoke(obj);
System.out.println(name);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // convert string classname to class
}
}
Output :
Ram
null
That is beause you are invoking the method on newly created object (e.g. obj) which does not have values set for variable1 and variable2, e.g.:
Object obj = newClass.newInstance();
The above will create a new Object of Bean class with null values for variable1 and variable2. If you want to print the values set in beanobject method then you need to invoke the getter method with beanobject. i.e. change
String name = (String) getNameMethod.invoke(obj);
to
String name = (String) getNameMethod.invoke(beanobject);
You create a new instance of the target class where no values set.
Object obj = newClass.newInstance();
Method getNameMethod = obj.getClass().getMethod(getMethod);
Change this line and it should work:
Method getNameMethod = beanobject.getClass().getMethod(getMethod);
Additional:
Your naming of variables isn't very good. I would refactoring the code to this for better reading:
public static void main(String[] args) {
Bean beanInstance = new Bean();
beanInstance.setVariable1("Ram");
beanInstance.setVariable2("Rakesh");
System.out.println("Value 1 of fresh bean instance: " + beanInstance.getVariable1());
String beanType = Bean.class.getName();
Class<?> beanClazz;
try {
beanClazz = Class.forName(beanType);
String getterMethodName = "getVariable2";
Method getterMethod = beanClazz.getMethod(getterMethodName);
Object returnValue = getterMethod.invoke(beanInstance);
System.out.println("Value 2 of by reflection loaded bean instance: " + String.valueOf(returnValue));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // convert string classname to class
}
Related
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'm trying to insert a method dynamically in an enum.
private void loadEnums(ServletContextEvent sce) {
List<Class<?>> classes = CPScanner.scanClasses(new ClassFilter().packageName("br.com.alinesolutions.anotaai.*").annotation(EnumSerialize.class));
CtClass ctClass = null;
EnumMemberValue enumMemberValue;
try {
for (Class<?> clazz : classes) {
if (!Enum.class.isAssignableFrom(clazz)) {
throw new RuntimeException("class " + clazz + " is not an instance of Enum");
}
ClassPool.getDefault().insertClassPath(new ClassClassPath(clazz));
ctClass = ClassPool.getDefault().get(clazz.getName());
for (CtField field : ctClass.getFields()) {
System.out.println(field);
//CtMethod m = CtNewMethod.make("public String getType() { return this.toString(); }", ctClass);
//ctClass.addMethod(m);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
how to create a method in enum field?
I assume that you try to create a method within an enumeration, i.e.
enum Foo {
BAR {
void qux() { }
}
}
The Java compiler creates such a method by creating a specific class that subclasses Foo and adds the method to this class. You would need to remove the final modifier from Foo, create such a subclass and replace the static initializer that creates the enum field for this.
I use RESTEasy for serializing enum objects and need to put the annotation
#JsonFormat(shape = JsonFormat.Shape.OBJECT)
and create a method with the anotation
#JsonCreator
need to create a method for each enum for this.
I have to create the methods, fromObject getProperty and getType dynamically for all enums, the method fromObject is static. that is, a difference to create this method. I created a annotation and when the context initialize want build these methods
package br.com.alinesolutions.anotaai.metadata.model.domain;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
#JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum TipoAcesso {
EMAIL("E-Mail"),
TELEFONE("Telefone");
private String descricao;
private TipoAcesso(String descricao) {
this.descricao = descricao;
}
public String getDescricao() {
return descricao;
}
// TODO - Adicionar metodos dinamicamente
public String getType() {
return this.toString();
}
public String getPropertieKey() {
StringBuilder sb = new StringBuilder("enum.");
sb.append(this.getClass().getName()).append(".");
sb.append(toString());
return sb.toString().toLowerCase();
}
#JsonCreator
public static TipoAcesso fromObject(JsonNode node) {
String type = null;
if (node.getNodeType().equals(JsonNodeType.STRING)) {
type = node.asText();
} else {
if (!node.has("type")) {
throw new IllegalArgumentException();
}
type = node.get("type").asText();
}
return valueOf(type);
}
}
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 a 2 POJO classes with getters and setters,now i am trying to get all the class instance variables of that class.
I got to know that we can use reflection how to do it?
This is my POJO Class which will extend my reflection class.
class Details{
private int age;
private String name;
}
Reflection class is like this:
class Reflection{
public String toString(){
return all the fields of that class
}
You could do something like this:
public void printFields(Object obj) throws Exception {
Class<?> objClass = obj.getClass();
Field[] fields = objClass.getFields();
for(Field field : fields) {
String name = field.getName();
Object value = field.get(obj);
System.out.println(name + ": " + value.toString());
}
}
This would only print the public fields, to print private fields use class.getDeclaredFields recursively.
Or if you would extend the class:
public String toString() {
try {
StringBuffer sb = new StringBuffer();
Class<?> objClass = this.getClass();
Field[] fields = objClass.getFields();
for(Field field : fields) {
String name = field.getName();
Object value = field.get(this);
sb.append(name + ": " + value.toString() + "\n");
}
return sb.toString();
} catch(Exception e) {
e.printStackTrace();
return null;
}
}
Adding one more line to the above code. If you want to access the private properties of the class use below line
field.setAccessible(true);
ClassLoader classLoader = Main.class.getClassLoader();
try {
Class cls = classLoader.loadClass("com.example.Example");
Object clsObject = cls.newInstance();
Field[] fields = cls.getFields();
for (Field field : fields) {
String name = field.getName();
Object value = field.get(clsObject);
System.out.println("Name : "+name+" Value : "+value);
}
System.out.println(cls.getName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The resolution code or answer which mentioned above has one issue.
To access the value of a private varible their access type must be set to true
Field[] fields = objClass.getDeclaredFields();
for (Field field : fields) {
NotNull notNull = field.getAnnotation(NotNull.class);
field.setAccessible(true);
}
else it will throw java.lang.IllegalAccessException. Class Reflection can not access a member of class Details with modifiers "private"
The objective is simple, I want to create a method which load a class dynamically, access its method and passing their parameters value and getting the return value at run-time.
Class which will be called
class MyClass {
public String sayHello() {
return "Hello";
}
public String sayGoodbye() {
return "Goodbye";
}
public String saySomething(String word){
return word;
}
}
Main Class
public class Main {
public void loadClass() {
try {
Class myclass = Class.forName(getClassName());
//Use reflection to list methods and invoke them
Method[] methods = myclass.getMethods();
Object object = myclass.newInstance();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().startsWith("saySome")) {
String word = "hello world";
//**TODO CALL OBJECT METHOD AND PASS ITS PARAMETER**
} else if (methods[i].getName().startsWith("say")) {
//call method
System.out.println(methods[i].invoke(object));
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private String getClassName() {
//Do appropriate stuff here to find out the classname
return "com.main.MyClass";
}
public static void main(String[] args) throws Exception {
new Main().loadClass();
}
}
My question is how to invoke method with parameters and passing its value? also getting the return value and its type.
I think you're just missing the fact that you can pass in arguments to invoke, as an Object[]:
Object result = methods[i].invoke(object, new Object[] { word });
Or using varargs, if you prefer:
Object result = methods[i].invoke(object, word);
(The above two calls are equivalent.)
See the documentation for Method.invoke for more details.
simply create the object of MyClass invoke the function like this
MyClass mc = new MyClass();
String word = "hello world";
String returnValue = mc.saySomething(word);
System.out.println(returnValue);//return hello world here
or do this
Class myclass = Class.forName(getClassName());
Method mth = myclass.getDeclaredMethod(methodName, params);
Object obj = myclass.newInstance();
String result = (String)mth.invoke(obj, args);
Try ::
Class c = Class.forName(className);
Method m = c.getDeclaredMethod(methodName, params);
Object i = c.newInstance();
String result = (String)m.invoke(i, args);