Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
shz.core.AccessibleHelp Maven / Gradle / Ivy
package shz.core;
import shz.core.cache.SimpleCache;
import shz.core.constant.NullConstant;
import shz.core.msg.ServerFailureMsg;
import shz.core.type.TypeHelp;
import java.lang.reflect.*;
import java.util.*;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
@SuppressWarnings("unchecked")
public final class AccessibleHelp {
private AccessibleHelp() {
throw new IllegalStateException();
}
private static final SimpleCache, List> FIELDS_CACHE = new SimpleCache<>();
/**
* 获取域
*
* @param cls 类的class对象
* @param filter 域过滤器
* @param limit 限制获取属性个数
* @param cache 是否缓存(若使用缓存,返回集合约定不可修改)
*/
public static List fields(Class> cls, Predicate filter, int limit, boolean cache) {
if (cls == null) return Collections.emptyList();
if (cache) {
List fields = FIELDS_CACHE.get(cls, () -> {
List result = new ArrayList<>();
Class> cur = cls;
do {
result.addAll(Arrays.asList(cur.getDeclaredFields()));
cur = cur.getSuperclass();
} while (cur != null && cur != Object.class);
return result.isEmpty() ? Collections.emptyList() : new ArrayList<>(result);
});
if (fields.isEmpty()) return Collections.emptyList();
if (filter == null) return fields;
if (limit <= 0) return ToList.explicitCollect(fields.stream().filter(filter), fields.size());
return ToList.explicitCollect(fields.stream().filter(filter).limit(limit), limit);
}
List result = new ArrayList<>();
int size = 0;
Class> cur = cls;
do {
for (Field f : cur.getDeclaredFields()) {
if (filter != null && !filter.test(f)) continue;
result.add(f);
++size;
if (limit > 0 && size >= limit) break;
}
cur = cur.getSuperclass();
} while (cur != null && cur != Object.class);
return result.isEmpty() ? Collections.emptyList() : result;
}
public static List fields(Class> cls, Predicate filter, int limit) {
return fields(cls, filter, limit, true);
}
public static List fields(Class> cls, Predicate filter) {
return fields(cls, filter, 0, true);
}
public static List fields(Class> cls) {
return fields(cls, null, 0, true);
}
private static final SimpleCache, List> METHODS_CACHE = new SimpleCache<>();
/**
* 获取类的方法
*/
public static List methods(Class> cls, Predicate filter, int limit, boolean cache) {
if (cls == null) return Collections.emptyList();
if (cache) {
List methods = METHODS_CACHE.get(cls, () -> {
List result = new ArrayList<>();
Class> cur = cls;
do {
result.addAll(Arrays.asList(cur.getDeclaredMethods()));
cur = cur.getSuperclass();
} while (cur != null && cur != Object.class);
return result.isEmpty() ? Collections.emptyList() : new ArrayList<>(result);
});
if (methods.isEmpty()) return Collections.emptyList();
if (filter == null) return methods;
if (limit <= 0) return ToList.explicitCollect(methods.stream().filter(filter), methods.size());
return ToList.explicitCollect(methods.stream().filter(filter).limit(limit), limit);
}
List result = new ArrayList<>();
int size = 0;
Class> cur = cls;
do {
for (Method m : cur.getDeclaredMethods()) {
if (filter != null && !filter.test(m)) continue;
result.add(m);
++size;
if (limit > 0 && size >= limit) break;
}
cur = cur.getSuperclass();
} while (cur != null && cur != Object.class);
return result.isEmpty() ? Collections.emptyList() : result;
}
public static List methods(Class> cls, Predicate filter, int limit) {
return methods(cls, filter, limit, true);
}
public static List methods(Class> cls, Predicate filter) {
return methods(cls, filter, 0, true);
}
public static List methods(Class> cls) {
return methods(cls, null, 0, true);
}
private static Field accessible(Field field) {
if (field.isAccessible()) return field;
if ((field.getModifiers() & Modifier.PUBLIC) == 0
|| (field.getDeclaringClass().getModifiers() & Modifier.PUBLIC) == 0
|| (field.getModifiers() & Modifier.FINAL) != 0)
field.setAccessible(true);
return field;
}
private static Method accessible(Method method) {
if (method.isAccessible()) return method;
if ((method.getModifiers() & Modifier.PUBLIC) == 0
|| (method.getDeclaringClass().getModifiers() & Modifier.PUBLIC) == 0)
method.setAccessible(true);
return method;
}
private static Constructor accessible(Constructor constructor) {
if (constructor.isAccessible()) return constructor;
if ((constructor.getModifiers() & Modifier.PUBLIC) == 0
|| (constructor.getDeclaringClass().getModifiers() & Modifier.PUBLIC) == 0)
constructor.setAccessible(true);
return constructor;
}
public static T getField(Field field, Object obj) {
if (field == null) return null;
try {
return (T) accessible(field).get(obj);
} catch (Exception e) {
return null;
}
}
public static boolean setField(Field field, Object obj, Object value) {
if (field == null || obj == null) return false;
try {
accessible(field).set(obj, value);
return true;
} catch (Exception ignored) {
return false;
}
}
public static T newInstance(Class extends T> cls) {
if (cls == null) return null;
try {
return ((Constructor) accessible(cls.getDeclaredConstructor())).newInstance();
} catch (Exception e) {
if (List.class.isAssignableFrom(cls)) return (T) new ArrayList<>();
if (Set.class.isAssignableFrom(cls)) return (T) new LinkedHashSet<>();
if (Map.class.isAssignableFrom(cls)) return (T) new LinkedHashMap<>();
}
return null;
}
public static T newInstance(Class extends T> cls, Object arg) {
if (arg == null) {
for (Constructor> constructor : cls.getDeclaredConstructors()) {
if (constructor.getParameterCount() == 1) {
try {
return (T) accessible(constructor).newInstance((Object) null);
} catch (Exception ignored) {
}
}
}
return null;
}
Class> paramType = arg.getClass();
Constructor> bestMatch = null;
for (Constructor> constructor : cls.getDeclaredConstructors()) {
if (constructor.getParameterCount() == 1) {
Class> parameterType = constructor.getParameterTypes()[0];
if (parameterType == paramType) {
bestMatch = constructor;
break;
}
if (bestMatch == null) {
if (parameterType.isAssignableFrom(paramType)) bestMatch = constructor;
} else if (bestMatch.getParameterTypes()[0].isAssignableFrom(parameterType)) bestMatch = constructor;
}
}
if (bestMatch == null) return null;
try {
return (T) accessible(bestMatch).newInstance(arg);
} catch (Exception e) {
return null;
}
}
public static T newInstance(Class extends T> cls, Object... args) {
List> constructors = new ArrayList<>();
for (Constructor> constructor : cls.getDeclaredConstructors())
if (constructor.getParameterCount() == args.length) constructors.add(constructor);
if (constructors.isEmpty()) return null;
Constructor> constructor;
if (constructors.size() == 1) constructor = constructors.get(0);
else {
Class>[][] psa = constructors.stream().map(Constructor::getParameterTypes).toArray(Class[][]::new);
Class>[] paramTypes = Arrays.stream(args).map(arg -> arg == null ? Object.class : arg.getClass()).toArray(Class[]::new);
constructor = constructors.get(TypeHelp.bestMatchParamTypes(psa, paramTypes));
}
try {
return (T) accessible(constructor).newInstance(args);
} catch (Exception e) {
return null;
}
}
public static T invoke(Method method, Object obj, Object... args) {
try {
if (method.getReturnType() == void.class) accessible(method).invoke(obj, args);
else return (T) accessible(method).invoke(obj, args);
} catch (Exception e) {
throw PRException.of(e);
}
return null;
}
public static T getField(Object obj, Predicate filter) {
List fields;
if (obj == null || (fields = fields(obj.getClass(), filter, 1)).isEmpty()) return null;
return getField(fields.get(0), obj);
}
public static boolean setField(Object obj, Predicate filter, Object value) {
List fields;
if (obj == null || (fields = fields(obj.getClass(), filter, 1)).isEmpty()) return false;
return setField(fields.get(0), obj, value);
}
public static void setField(Object obj, Function func) {
if (obj == null || func == null) return;
List fields = fields(obj.getClass());
if (fields.isEmpty()) return;
fields.forEach(f -> {
Object value = func.apply(f);
if (value == NullConstant.OBJECT) return;
setField(f, obj, value);
});
}
public static void setField(Object obj, BiFunction, Field, Object> func) {
if (obj == null || func == null) return;
List fields = fields(obj.getClass());
if (fields.isEmpty()) return;
Map nameMap = ToMap.explicitCollect(fields.stream(), Field::getName, Function.identity(), fields.size());
fields.forEach(f -> {
Object value = func.apply(nameMap, f);
if (value == NullConstant.OBJECT) return;
setField(f, obj, value);
});
}
/**
* 根据方法名称获取空参方法
*/
public static Method getMethod(Class> cls, String methodName) {
List methods = methods(cls, m -> m.getName().equals(methodName) && m.getParameterCount() == 0, 1);
return methods.isEmpty() ? null : methods.get(0);
}
/**
* 根据方法名称及参数类型获取一个参数的方法
*/
public static Method getMethod(Class> cls, String methodName, Class> paramType) {
List methods = methods(cls, m -> {
if (!m.getName().equals(methodName)) return false;
Class>[] ptypes = m.getParameterTypes();
return ptypes.length == 1 && ptypes[0].isAssignableFrom(paramType);
}, 0);
if (methods.isEmpty()) return null;
if (methods.size() == 1) return methods.get(0);
Class>[] pa = methods.stream().map(m -> m.getParameterTypes()[0]).toArray(Class[]::new);
int idx = 0;
for (int i = 1; i < pa.length; ++i) {
if (pa[idx] == paramType) break;
if (pa[idx].isAssignableFrom(pa[i])) idx = i;
}
return methods.get(idx);
}
/**
* 根据方法名称及参数类型获取二个参数的方法
*/
public static Method getMethod(Class> cls, String methodName, Class> paramType1, Class> paramType2) {
List methods = methods(cls, m -> {
if (!m.getName().equals(methodName)) return false;
Class>[] ptypes = m.getParameterTypes();
return ptypes.length == 2 && ptypes[0].isAssignableFrom(paramType1) && ptypes[1].isAssignableFrom(paramType2);
}, 0);
if (methods.isEmpty()) return null;
if (methods.size() == 1) return methods.get(0);
Class>[][] psa = methods.stream().map(Method::getParameterTypes).toArray(Class[][]::new);
return methods.get(TypeHelp.bestMatchParamTypes(psa, paramType1, paramType2));
}
/**
* 根据方法名称及参数类型获取多个参数的方法
*/
public static Method getMethod(Class> cls, String methodName, Class>... paramTypes) {
List methods = methods(cls, m -> {
if (!m.getName().equals(methodName)) return false;
Class>[] pTypes = m.getParameterTypes();
if (pTypes.length != paramTypes.length) return false;
for (int i = 0; i < pTypes.length; ++i) if (!pTypes[i].isAssignableFrom(paramTypes[i])) return false;
return true;
}, 0);
if (methods.isEmpty()) return null;
if (methods.size() == 1) return methods.get(0);
Class>[][] psa = methods.stream().map(Method::getParameterTypes).toArray(Class[][]::new);
return methods.get(TypeHelp.bestMatchParamTypes(psa, paramTypes));
}
/**
* 通过反射执行方法
*/
public static T invoke(Object obj, String methodName) {
return invoke(getMethod(Objects.requireNonNull(obj).getClass(), methodName), obj);
}
public static T invoke(Object obj, String methodName, Class> paramType, Object arg) {
return invoke(getMethod(Objects.requireNonNull(obj).getClass(), methodName, paramType), obj, arg);
}
public static T invoke(Object obj, String methodName, Class>[] paramTypes, Object[] args) {
return invoke(getMethod(Objects.requireNonNull(obj).getClass(), methodName, paramTypes), obj, args);
}
public static T invoke(Object obj, Method method, Function paramNamesFunc, Map data) {
Class>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 0) return invoke(method, obj);
String[] paramNames = paramNamesFunc.apply(method);
ServerFailureMsg.requireNon(NullHelp.length(paramNames) != parameterTypes.length, "参数名称列表与参数类型列表长度不一致");
Type[] genericParameterTypes = method.getGenericParameterTypes();
Object[] args = new Object[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; ++i) {
if (TypeHelp.likeCommon(parameterTypes[i]))
args[i] = FieldSetter.cast(data.get(paramNames[i]), parameterTypes[i]);
else args[i] = FieldSetter.create(data, parameterTypes[i], genericParameterTypes[i]);
}
return invoke(method, obj, args);
}
}