xdean.jex.util.reflect.ReflectUtil Maven / Gradle / Ivy
The newest version!
package xdean.jex.util.reflect;
import static xdean.jex.util.lang.ExceptionUtil.uncheck;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.function.UnaryOperator;
public class ReflectUtil {
private static final UnaryOperator EXECUTABLE_GET_ROOT;
private static final Function, Method[]> CLASS_GET_ROOT_METHODS;
private static final UnaryOperator FIELD_GET_ROOT;
private static final Function, Field[]> CLASS_GET_ROOT_FIELDS;
static {
try {
Method getRootMethod = Executable.class.getDeclaredMethod("getRoot");
getRootMethod.setAccessible(true);
EXECUTABLE_GET_ROOT = m -> uncheck(() -> (Executable) getRootMethod.invoke(m));
Method getRootMethods = Class.class.getDeclaredMethod("privateGetPublicMethods");
getRootMethods.setAccessible(true);
CLASS_GET_ROOT_METHODS = c -> uncheck(() -> (Method[]) getRootMethods.invoke(c));
Field getRootField = Field.class.getDeclaredField("root");
getRootField.setAccessible(true);
FIELD_GET_ROOT = f -> uncheck(() -> (Field) getRootField.get(f));
Method getRootFields = Class.class.getDeclaredMethod("privateGetPublicFields", Set.class);
getRootFields.setAccessible(true);
CLASS_GET_ROOT_FIELDS = c -> uncheck(() -> (Field[]) getRootFields.invoke(c, new Object[] { null }));
} catch (NoSuchMethodException | SecurityException | NoSuchFieldException e) {
throw new IllegalStateException("ReflectUtil init fail, check your java version.", e);
}
}
public static void setModifiers(AccessibleObject ao, int modifier) {
Arrays.stream(getAllFields(ao.getClass()))
.filter(f -> f.getName().equals("modifiers"))
.peek(f -> f.setAccessible(true))
.forEach(f -> uncheck(() -> f.set(ao, modifier)));
}
/**
* Get root of the method.
*/
public static Method getRootMethod(Method m) {
return getRootExecutable(m);
}
/**
* Get root of the executable.
*/
@SuppressWarnings("unchecked")
public static T getRootExecutable(T m) {
return (T) EXECUTABLE_GET_ROOT.apply(m);
}
/**
* Get root public methods of the class.
*/
public static Method[] getRootMethods(Class> clz) {
return CLASS_GET_ROOT_METHODS.apply(clz);
}
/**
* Get root of the field.
*/
public static Field getRootField(Field f) {
return FIELD_GET_ROOT.apply(f);
}
/**
* Get root public fields of the class.
*/
public static Field[] getRootFields(Class> clz) {
return CLASS_GET_ROOT_FIELDS.apply(clz);
}
/**
* Get field value by name
*
* @param clz
* @param t
* @param fieldName
* @return
* @throws NoSuchFieldException
*/
@SuppressWarnings("unchecked")
public static O getFieldValue(Class clz, T t, String fieldName) throws NoSuchFieldException {
Field field = clz.getDeclaredField(fieldName);
field.setAccessible(true);
try {
return (O) field.get(t);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
/**
* Get all fields
*
* @param clz
* @param includeStatic include static fields or not
* @return
*/
public static Field[] getAllFields(Class> clz, boolean includeStatic) {
return Arrays.stream(getAllFields(clz))
.filter(f -> includeStatic || !Modifier.isStatic(f.getModifiers()))
.toArray(Field[]::new);
}
/**
* Get all fields
*
* @param clz
* @return
*/
public static Field[] getAllFields(Class> clz) {
List list = new ArrayList<>();
do {
list.addAll(Arrays.asList(clz.getDeclaredFields()));
} while ((clz = clz.getSuperclass()) != null);
return list.toArray(new Field[list.size()]);
}
/**
* Get all methods
*
* @param clz
* @return
*/
public static Method[] getAllMethods(Class> clz) {
Set set = new HashSet<>();
List> classes = new ArrayList<>();
classes.add(clz);
classes.addAll(Arrays.asList(getAllSuperClasses(clz)));
classes.addAll(Arrays.asList(getAllInterfaces(clz)));
for (Class> c : classes) {
set.addAll(Arrays.asList(c.getDeclaredMethods()));
}
return set.toArray(new Method[set.size()]);
}
/**
* Get all super classes
*
* @param clz
* @return
*/
public static Class>[] getAllSuperClasses(Class> clz) {
List> list = new ArrayList<>();
while ((clz = clz.getSuperclass()) != null) {
list.add(clz);
}
return list.toArray(new Class>[list.size()]);
}
/**
* Get all interfaces
*
* @param clz
* @return
*/
public static Class>[] getAllInterfaces(Class> clz) {
HashSet> set = new HashSet<>();
getAllInterfaces(clz, set);
return set.toArray(new Class>[set.size()]);
}
private static void getAllInterfaces(Class> clz, Set> visited) {
if (clz.getSuperclass() != null) {
getAllInterfaces(clz.getSuperclass(), visited);
}
for (Class> c : clz.getInterfaces()) {
if (visited.add(c)) {
getAllInterfaces(c, visited);
}
}
}
/**
* Get the name of the class who calls the caller.
* For example. The following code will print "A".
*
*
* class A {
* static void fun() {
* B.fun();
* }
* }
*
* class B {
* static void fun() {
* System.out.println(ReflectUtil.getCallerClassName());
* }
* }
*
*
* @return
*/
public static String getCallerClassName() {
return getCaller().getClassName();
}
public static StackTraceElement getCaller() {
return getCaller(1, true);
}
/**
* Get caller stack info.
*
* @param deep Deep to search the caller class.If deep is 0, it returns the class who calls this method.
* @param ignoreSameClass If it is true, calling in same class will be ignored.
* @return
*/
public static StackTraceElement getCaller(int deep, boolean ignoreSameClass) {
// index 0 is Thread.getStackTrace
// index 1 is ReflectUtil.getCallerClassName
StackTraceElement[] stElements = Thread.currentThread().getStackTrace();
StackTraceElement currentStack = stElements[1];
int found = deep + 1;
for (int i = 1; i < stElements.length; i++) {
StackTraceElement nextStack = stElements[i];
if (nextStack.getClassName().equals(ReflectUtil.class.getName())) {
continue;
}
if (!ignoreSameClass || !currentStack.getClassName().equals(nextStack.getClassName())) {
currentStack = nextStack;
found--;
}
if (found == 0) {
return currentStack;
}
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy