Created
December 8, 2023 16:28
-
-
Save IllusionTheDev/e7b00a7dc8f4007e56f426bb0c2cf22a to your computer and use it in GitHub Desktop.
Reflection Helper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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