Tuesday, 9 May 2023

Utility class to work with reflections in Java

In this post, I am going to explain about an utility class to made your work easier while working with reflections.

 

Utility class provide below methods.

a.   Get an instance of an object

b.   Invoke an instance method with or without arguments

c.    Invoke static method with or without arguments

d.   Get the value of instance property

e.   Set the value to an instance property

f.     Check for the existence of given method name


Get an instance of an object

public static Object newInstance(String classFullName) throws Throwable {
	try {
		Class<?> clazz = Class.forName(classFullName, true, ReflectionUtil.class.getClassLoader());
		Constructor<?> constructor = clazz.getConstructor();
		return constructor.newInstance();
	} catch (Throwable t) {
		throw t;
	}
}

public static <T> T newInstance(Class<T> ofClass, Class<?>[] argTypes, Object[] args) throws Throwable {
	try {
		Constructor<T> con = ofClass.getConstructor(argTypes);
		return con.newInstance(args);
	} catch (Throwable t) {
		throw t;
	}
}

 

Invoke an instance method with or without arguments

public static <T> T invokeMethod(Object obj, String methodName) throws Throwable {
	try {
		Method method = obj.getClass().getMethod(methodName);
		return (T) method.invoke(obj);
	} catch (Throwable t) {
		throw t;
	}
}

public static <T> T invokeMethod(Object obj, String methodName, Class<?> argType, Object arg) throws Throwable {
	try {
		Method method = obj.getClass().getMethod(methodName, argType);
		return (T) method.invoke(obj, arg);
	} catch (Throwable t) {
		throw t;
	}
}

public static <T> T invokeMethod(Object obj, String methodName, Class<?> argType1, Object arg1, Class<?> argType2,
		Object arg2) throws Throwable {
	try {
		Method method = obj.getClass().getMethod(methodName, argType1, argType2);
		return (T) method.invoke(obj, arg1, arg2);
	} catch (Throwable t) {
		throw t;
	}
}

public static <T> T invokeMethod(Object obj, String methodName, Class<?>[] argTypes, Object[] args)
		throws Throwable {
	try {
		Method method = obj.getClass().getMethod(methodName, argTypes);
		return (T) method.invoke(obj, args);
	} catch (Throwable t) {
		throw t;
	}
}

 

c. Invoke static method with or without arguments

public static <T> T invokeStaticMethod(Class<?> clazz, String methodName) throws Throwable {
	try {
		Method method = clazz.getDeclaredMethod(methodName);
		return (T) method.invoke(null);
	} catch (Throwable t) {
		throw t;
	}
}

public static <T> T invokeStaticMethod(Class<?> clazz, String methodName, Class<?> argType, Object arg)
		throws Throwable {
	try {
		Method method = clazz.getDeclaredMethod(methodName, argType);
		return (T) method.invoke(null, arg);
	} catch (Throwable t) {
		throw t;
	}
}

public static <T> T invokeStaticMethod(Class<?> clazz, String methodName, Class<?> argType1, Object arg1,
		Class<?> argType2, Object arg2) throws Throwable {
	try {
		Method method = clazz.getDeclaredMethod(methodName, argType1, argType2);
		return (T) method.invoke(null, arg1, arg2);
	} catch (Throwable t) {
		throw t;
	}
}

public static <T> T invokeStaticMethod(Class<?> clazz, String methodName, Class<?>[] argTypes, Object[] args)
		throws Throwable {
	try {
		Method method = clazz.getDeclaredMethod(methodName, argTypes);
		return (T) method.invoke(null, args);
	} catch (Throwable t) {
		throw t;
	}
}

 

Get the value of instance property

public static <T> T getField(Object obj, String fieldName) throws Throwable {
	try {
		Field field = obj.getClass().getDeclaredField(fieldName);
		field.setAccessible(true);
		return (T) field.get(obj);
	} catch (Throwable t) {
		throw t;
	}
}

 

Set the value to an instance property

public static void setField(Object obj, String fieldName, Object value) throws Throwable {
	try {
		Field field = obj.getClass().getDeclaredField(fieldName);
		field.setAccessible(true);
		field.set(obj, value);
	} catch (Throwable t) {
		throw t;
	}
}

 

Check for existence of given method name

public static boolean isMethodExists(Object o, String methodName) {
	try {
		return Stream.of(o.getClass().getDeclaredMethods()).map(Method::getName)
				.anyMatch(Predicate.isEqual(methodName));
	} catch (Throwable t) {
		throw t;
	}
}

 

Find the below working application.

 

Employee.java

 

package com.sample.app.model;

import java.util.List;

public class Employee {

	private int id;
	private String name;
	private int age;

	public Employee() {}

	public Employee(int id, String name, int age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	public void updateDetails(int id, String name, int age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}
	
	public static Employee olderEmployee(List<Employee> emps) {
		if(emps == null || emps.isEmpty()) {
			return null;
		}
		
		Employee maxAgeEmp = new Employee(-1,"", -1);
		for(Employee emp: emps) {
			if(emp.age > maxAgeEmp.age) {
				maxAgeEmp = emp;
			}
		}
		
		return maxAgeEmp;
	}
	
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", age=" + age + "]";
	}

}

 

ReflectionUtil.java

package com.sample.app.reflections.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class ReflectionUtil {

	public static Object newInstance(String classFullName) throws Throwable {
		try {
			Class<?> clazz = Class.forName(classFullName, true, ReflectionUtil.class.getClassLoader());
			Constructor<?> constructor = clazz.getConstructor();
			return constructor.newInstance();
		} catch (Throwable t) {
			throw t;
		}
	}

	public static <T> T newInstance(Class<T> ofClass, Class<?>[] argTypes, Object[] args) throws Throwable {
		try {
			Constructor<T> con = ofClass.getConstructor(argTypes);
			return con.newInstance(args);
		} catch (Throwable t) {
			throw t;
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T invokeMethod(Object obj, String methodName) throws Throwable {
		try {
			Method method = obj.getClass().getMethod(methodName);

			// this is required to access private methods too
			method.setAccessible(true);
			return (T) method.invoke(obj);
		} catch (Throwable t) {
			throw t;
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T invokeMethod(Object obj, String methodName, Class<?> argType, Object arg) throws Throwable {
		try {
			Method method = obj.getClass().getMethod(methodName, argType);
			method.setAccessible(true);
			return (T) method.invoke(obj, arg);
		} catch (Throwable t) {
			throw t;
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T invokeMethod(Object obj, String methodName, Class<?> argType1, Object arg1, Class<?> argType2,
			Object arg2) throws Throwable {
		try {
			Method method = obj.getClass().getMethod(methodName, argType1, argType2);
			method.setAccessible(true);
			return (T) method.invoke(obj, arg1, arg2);
		} catch (Throwable t) {
			throw t;
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T invokeMethod(Object obj, String methodName, Class<?>[] argTypes, Object[] args)
			throws Throwable {
		try {
			Method method = obj.getClass().getMethod(methodName, argTypes);
			method.setAccessible(true);
			return (T) method.invoke(obj, args);
		} catch (Throwable t) {
			throw t;
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T invokeStaticMethod(Class<?> clazz, String methodName) throws Throwable {
		try {
			Method method = clazz.getDeclaredMethod(methodName);
			method.setAccessible(true);
			return (T) method.invoke(null);
		} catch (Throwable t) {
			throw t;
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T invokeStaticMethod(Class<?> clazz, String methodName, Class<?> argType, Object arg)
			throws Throwable {
		try {
			Method method = clazz.getDeclaredMethod(methodName, argType);
			method.setAccessible(true);
			return (T) method.invoke(null, arg);
		} catch (Throwable t) {
			throw t;
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T invokeStaticMethod(Class<?> clazz, String methodName, Class<?> argType1, Object arg1,
			Class<?> argType2, Object arg2) throws Throwable {
		try {
			Method method = clazz.getDeclaredMethod(methodName, argType1, argType2);
			method.setAccessible(true);
			return (T) method.invoke(null, arg1, arg2);
		} catch (Throwable t) {
			throw t;
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T invokeStaticMethod(Class<?> clazz, String methodName, Class<?>[] argTypes, Object[] args)
			throws Throwable {
		try {
			Method method = clazz.getDeclaredMethod(methodName, argTypes);
			method.setAccessible(true);
			return (T) method.invoke(null, args);
		} catch (Throwable t) {
			throw t;
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T getField(Object obj, String fieldName) throws Throwable {
		try {
			Field field = obj.getClass().getDeclaredField(fieldName);
			field.setAccessible(true);
			return (T) field.get(obj);
		} catch (Throwable t) {
			throw t;
		}
	}

	public static void setField(Object obj, String fieldName, Object value) throws Throwable {
		try {
			Field field = obj.getClass().getDeclaredField(fieldName);
			field.setAccessible(true);
			field.set(obj, value);
		} catch (Throwable t) {
			throw t;
		}
	}

	public static boolean isMethodExists(Object o, String methodName) {
		try {
			return Stream.of(o.getClass().getDeclaredMethods()).map(Method::getName)
					.anyMatch(Predicate.isEqual(methodName));
		} catch (Throwable t) {
			throw t;
		}
	}

}

ReflectionUtilDemo.java

package com.sample.app;

import java.util.Arrays;
import java.util.List;

import com.sample.app.model.Employee;
import com.sample.app.reflections.util.ReflectionUtil;

public interface ReflectionUtilDemo {

	private static void newInstanceTest() throws Throwable {
		System.out.println("newInstanceTest example");
		Employee emp1 = (Employee) ReflectionUtil.newInstance("com.sample.app.model.Employee");

		Class<?>[] argTypes = { int.class, String.class, int.class };
		Object[] args = { 1, "Krishna", 34 };
		Employee emp2 = ReflectionUtil.newInstance(Employee.class, argTypes, args);

		System.out.println("emp1 : " + emp1);
		System.out.println("emp2 : " + emp2);
	}

	private static void invokeMethodTest() throws Throwable {
		System.out.println("\ninvokeMethodTest example");
		Employee emp1 = (Employee) ReflectionUtil.newInstance("com.sample.app.model.Employee");

		ReflectionUtil.invokeMethod(emp1, "setName", String.class, "Krishna");
		ReflectionUtil.invokeMethod(emp1, "setId", int.class, 1);
		ReflectionUtil.invokeMethod(emp1, "setAge", int.class, 35);

		System.out.println(emp1);

		Class<?>[] argTypes = { int.class, String.class, int.class };
		Object[] args = { 2, "Ram", 36 };
		ReflectionUtil.invokeMethod(emp1, "updateDetails", argTypes, args);
		System.out.println(emp1);
	}

	private static void invokeStaticMethodTest() throws Throwable {
		System.out.println("\ninvokeStaticMethodTest example");
		Employee emp1 = new Employee(1, "Krishna", 34);
		Employee emp2 = new Employee(2, "Sailu", 35);
		Employee emp3 = new Employee(3, "Bala", 41);
		Employee emp4 = new Employee(4, "Loopa", 26);

		List<Employee> emps = Arrays.asList(emp1, emp2, emp3, emp4);

		Employee olderEmployee = ReflectionUtil.invokeStaticMethod(Employee.class, "olderEmployee", List.class, emps);
		System.out.println(olderEmployee);
	}

	private static void getFieldTest() throws Throwable {
		System.out.println("\ngetFieldTest example");
		Employee emp1 = new Employee(1, "Krishna", 34);

		int id = (int) ReflectionUtil.getField(emp1, "id");
		String name = (String) ReflectionUtil.getField(emp1, "name");
		int age = (int) ReflectionUtil.getField(emp1, "age");

		System.out.println("id : " + id);
		System.out.println("name : " + name);
		System.out.println("age : " + age);

	}

	private static void setFieldTest() throws Throwable {
		System.out.println("\nsetFieldTest example");
		Employee emp1 = new Employee();

		ReflectionUtil.setField(emp1, "id", 1);
		ReflectionUtil.setField(emp1, "name", "Krishna");
		ReflectionUtil.setField(emp1, "age", 34);

		System.out.println(emp1);
	}

	private static void isMethodExistsTest() {
		System.out.println("\nisMethodExistsTest example");
		Employee emp1 = new Employee();

		boolean isSetIdExists = ReflectionUtil.isMethodExists(emp1, "setId");
		boolean isOlderEmployeeExists = ReflectionUtil.isMethodExists(emp1, "olderEmployee");
		boolean isSetABCExists = ReflectionUtil.isMethodExists(emp1, "setABC");

		System.out.println("setId exists : " + isSetIdExists);
		System.out.println("olderEmployee exists : " + isOlderEmployeeExists);
		System.out.println("setABC exists : " + isSetABCExists);
	}

	public static void main(String[] args) throws Throwable {
		newInstanceTest();

		invokeMethodTest();

		invokeStaticMethodTest();

		getFieldTest();

		setFieldTest();

		isMethodExistsTest();
	}

}

Output

newInstanceTest example
emp1 : Employee [id=0, name=null, age=0]
emp2 : Employee [id=1, name=Krishna, age=34]

invokeMethodTest example
Employee [id=1, name=Krishna, age=35]
Employee [id=2, name=Ram, age=36]

invokeStaticMethodTest example
Employee [id=3, name=Bala, age=41]

getFieldTest example
id : 1
name : Krishna
age : 34

setFieldTest example
Employee [id=1, name=Krishna, age=34]

isMethodExistsTest example
setId exists : true
olderEmployee exists : true
setABC exists : false


 

Previous                                                 Next                                                 Home

No comments:

Post a Comment