Skip to content

Instantly share code, notes, and snippets.

@IllusionTheDev
Created December 8, 2023 16:28
Show Gist options
  • Save IllusionTheDev/e7b00a7dc8f4007e56f426bb0c2cf22a to your computer and use it in GitHub Desktop.
Save IllusionTheDev/e7b00a7dc8f4007e56f426bb0c2cf22a to your computer and use it in GitHub Desktop.
Reflection Helper
public final class Reflect {
private Reflect() {
}
public static <T> ReflectedClass<T> aClass(Class<T> clazz) {
return new ReflectedClass<>(clazz);
}
public static <T> ReflectedField<T> aField(Class<T> clazz, String fieldName) {
return Reflect.aClass(clazz).getField(fieldName);
}
public static <T> ReflectedMethod aMethod(Class<T> clazz, String methodName) {
return Reflect.aClass(clazz).getMethod(methodName);
}
}
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ReflectedClass<T> {
private final Class<T> internalClass;
private final Map<String, ReflectedField<T>> fields;
private final Map<String, ReflectedMethod> methods;
public ReflectedClass(Class<T> internalClass) {
this.internalClass = internalClass;
this.fields = createFields();
this.methods = createMethods();
}
public ReflectedField<T> getField(String fieldName) {
return fields.get(fieldName);
}
public <V> V getField(T instance, String fieldName) {
return fields.get(fieldName).getValue(instance);
}
public void setField(T instance, String fieldName, Object value) {
fields.get(fieldName).setValue(instance, value);
}
public ReflectedMethod getMethod(String methodName) {
return methods.get(methodName);
}
public <V> V invoke(T instance, String methodName, Object... args) {
return (V) methods.get(methodName).invoke(instance, args);
}
public Class<T> getInternalClass() {
return internalClass;
}
private Map<String, ReflectedField<T>> createFields() {
Map<String, ReflectedField<T>> fields = new ConcurrentHashMap<>();
parseFields(internalClass, fields);
return fields;
}
private void parseFields(Class<?> clazz, Map<String, ReflectedField<T>> fields) {
for (Field field : clazz.getDeclaredFields()) {
fields.put(field.getName(), new ReflectedField<>(internalClass, field.getName()));
}
if (clazz.getSuperclass() != null && clazz.getSuperclass() != Object.class) {
parseFields(clazz.getSuperclass(), fields);
}
}
private Map<String, ReflectedMethod> createMethods() {
Map<String, ReflectedMethod> methods = new ConcurrentHashMap<>();
parseMethods(internalClass, methods);
return methods;
}
private void parseMethods(Class<?> clazz, Map<String, ReflectedMethod> methods) {
for (Method method : clazz.getDeclaredMethods()) {
methods.put(method.getName(), new ReflectedMethod(internalClass, method.getName()));
}
if (clazz.getSuperclass() != null && clazz.getSuperclass() != Object.class) {
parseMethods(clazz.getSuperclass(), methods);
}
}
}
import java.lang.reflect.Field;
public class ReflectedField<T> {
private final Class<T> internalClass;
private final String fieldName;
private final Class<?> fieldType;
private final Field field;
public ReflectedField(Class<T> internalClass, String fieldName) {
this.internalClass = internalClass;
this.fieldName = fieldName;
try {
this.field = internalClass.getDeclaredField(fieldName);
this.fieldType = field.getType();
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
public <V> V getValue(T instance) {
try {
return (V) field.get(instance);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public void setValue(T instance, Object value) {
try {
boolean accessible = field.isAccessible();
field.setAccessible(true);
field.set(instance, value);
field.setAccessible(accessible);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public Class<T> getInternalClass() {
return internalClass;
}
public String getFieldName() {
return fieldName;
}
public Class<?> getFieldType() {
return fieldType;
}
public Field getField() {
return field;
}
}
import java.lang.reflect.Method;
public class ReflectedMethod {
private final Class<?> internalClass;
private final String methodName;
private final Class<?>[] parameterTypes;
private final Method method;
public ReflectedMethod(Class<?> internalClass, String methodName) {
this.internalClass = internalClass;
this.methodName = methodName;
try {
this.method = internalClass.getDeclaredMethod(methodName);
this.parameterTypes = method.getParameterTypes();
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public <V> V invoke(Object instance, Object... args) {
boolean accessible = method.isAccessible();
try {
method.setAccessible(true);
return (V) method.invoke(instance, args);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
method.setAccessible(accessible);
}
}
public Class<?> getInternalClass() {
return internalClass;
}
public String getMethodName() {
return methodName;
}
public Class<?>[] getParameterTypes() {
return parameterTypes;
}
public Method getMethod() {
return method;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment