
com.taobao.hsf.util.ReflectUtils Maven / Gradle / Ivy
/*
* Copyright 1999-2011 Alibaba Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.taobao.hsf.util;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* ReflectUtils
*
* @author qian.lei
* @author kongming.lrq
*/
public final class ReflectUtils {
/**
* void(V).
*/
public static final char JVM_VOID = 'V';
/**
* boolean(Z).
*/
public static final char JVM_BOOLEAN = 'Z';
/**
* byte(B).
*/
public static final char JVM_BYTE = 'B';
/**
* char(C).
*/
public static final char JVM_CHAR = 'C';
/**
* double(D).
*/
public static final char JVM_DOUBLE = 'D';
/**
* float(F).
*/
public static final char JVM_FLOAT = 'F';
/**
* int(I).
*/
public static final char JVM_INT = 'I';
/**
* long(J).
*/
public static final char JVM_LONG = 'J';
/**
* short(S).
*/
public static final char JVM_SHORT = 'S';
public static final Class>[] EMPTY_CLASS_ARRAY = new Class>[0];
public static final String JAVA_IDENT_REGEX = "(?:[_$a-zA-Z][_$a-zA-Z0-9]*)";
public static final String CLASS_DESC = "(?:L" + JAVA_IDENT_REGEX + "(?:\\/" + JAVA_IDENT_REGEX + ")*;)";
public static final String ARRAY_DESC = "(?:\\[+(?:(?:[VZBCDFIJS])|" + CLASS_DESC + "))";
public static final String DESC_REGEX = "(?:(?:[VZBCDFIJS])|" + CLASS_DESC + "|" + ARRAY_DESC + ")";
public static final Pattern DESC_PATTERN = Pattern.compile(DESC_REGEX);
public static final Pattern GETTER_METHOD_DESC_PATTERN = Pattern.compile(
"get([A-Z][_a-zA-Z0-9]*)\\(\\)(" + DESC_REGEX + ")");
public static final Pattern SETTER_METHOD_DESC_PATTERN = Pattern.compile(
"set([A-Z][_a-zA-Z0-9]*)\\((" + DESC_REGEX + ")\\)V");
public static final Pattern IS_HAS_CAN_METHOD_DESC_PATTERN = Pattern.compile(
"(?:is|has|can)([A-Z][_a-zA-Z0-9]*)\\(\\)Z");
private static final ConcurrentMap> DESC_CLASS_CACHE = new ConcurrentHashMap>();
private static final ConcurrentMap> NAME_CLASS_CACHE = new ConcurrentHashMap>();
private static final ConcurrentMap Signature_METHODS_CACHE = new ConcurrentHashMap();
static private Map, Object> primitiveDefaults = new HashMap, Object>();
static {
primitiveDefaults.put(int.class, 0);
primitiveDefaults.put(long.class, 0L);
primitiveDefaults.put(byte.class, (byte) 0);
primitiveDefaults.put(char.class, (char) 0);
primitiveDefaults.put(short.class, (short) 0);
primitiveDefaults.put(float.class, (float) 0);
primitiveDefaults.put(double.class, (double) 0);
primitiveDefaults.put(boolean.class, false);
primitiveDefaults.put(void.class, null);
}
private ReflectUtils() {
}
/**
*
* 根据方法获取对应的默认返回值
*
*
* @param m 方法
* @return 如果是原型,返回对应的值,否则返回null
*/
static public Object defaultReturn(Method m) {
if (m.getReturnType().isPrimitive()) {
return primitiveDefaults.get(m.getReturnType());
} else {
return null;
}
}
/**
* 根据类型确定默认返回值
*
* @param classType 类型
* @return 默认值,如果是原型,返回对应的值,否则返回null
*/
static public Object defaultReturn(Class> classType) {
if (classType != null && classType.isPrimitive()) {
return primitiveDefaults.get(classType);
} else {
return null;
}
}
/**
* 递归判断当前类型是否原型
*
* @param cls 类型,如果是数组,则获取其元素类型
* @return 是否原型
*/
public static boolean isPrimitives(Class> cls) {
if (cls.isArray()) {
return isPrimitives(cls.getComponentType());
}
return isPrimitive(cls);
}
/**
*
* 是否原型
*
*
java原型
* 字符串java.lang.String
* Boolean包装类型
* Character包装
* Number的子类型
* java.util.Date
*
*
*
* @param cls 类型
* @return 是否原型
*/
public static boolean isPrimitive(Class> cls) {
return cls.isPrimitive() || cls == String.class || cls == Boolean.class || cls == Character.class
|| Number.class.isAssignableFrom(cls) || Date.class.isAssignableFrom(cls);
}
/**
* 获取类型的包装类型
*
* @param c 原型
* @return 包装类型
*/
public static Class> getBoxedClass(Class> c) {
if (c == int.class)
c = Integer.class;
else if (c == boolean.class)
c = Boolean.class;
else if (c == long.class)
c = Long.class;
else if (c == float.class)
c = Float.class;
else if (c == double.class)
c = Double.class;
else if (c == char.class)
c = Character.class;
else if (c == byte.class)
c = Byte.class;
else if (c == short.class)
c = Short.class;
return c;
}
/**
* is compatible.
*
* @param c class.
* @param o instance.
* @return compatible or not.
*/
public static boolean isCompatible(Class> c, Object o) {
boolean pt = c.isPrimitive();
if (o == null)
return !pt;
if (pt) {
if (c == int.class)
c = Integer.class;
else if (c == boolean.class)
c = Boolean.class;
else if (c == long.class)
c = Long.class;
else if (c == float.class)
c = Float.class;
else if (c == double.class)
c = Double.class;
else if (c == char.class)
c = Character.class;
else if (c == byte.class)
c = Byte.class;
else if (c == short.class)
c = Short.class;
}
if (c == o.getClass())
return true;
return c.isInstance(o);
}
/**
* is compatible.
*
* @param cs class array.
* @param os object array.
* @return compatible or not.
*/
public static boolean isCompatible(Class>[] cs, Object[] os) {
int len = cs.length;
if (len != os.length)
return false;
if (len == 0)
return true;
for (int i = 0; i < len; i++)
if (!isCompatible(cs[i], os[i]))
return false;
return true;
}
/**
* 获取当前类型的位置
*
* @param cls 类型
* @return 位置
*/
public static String getCodeBase(Class> cls) {
if (cls == null)
return null;
ProtectionDomain domain = cls.getProtectionDomain();
if (domain == null)
return null;
CodeSource source = domain.getCodeSource();
if (source == null)
return null;
URL location = source.getLocation();
if (location == null)
return null;
return location.getFile();
}
/**
* * get name. java.lang.Object[][].class => "java.lang.Object[][]" * java.lang.Object ==> "java.lang.Object" ** * @param c class. * @return name. */ public static String getName(Class> c) { if (c.isArray()) { StringBuilder sb = new StringBuilder(); do { sb.append("[]"); c = c.getComponentType(); } while (c.isArray()); return c.getName() + sb.toString(); } return c.getName(); } /** * 获取实现接口上的泛型类型 * * @param cls 类型 * @return 实现接口的泛型 */ public static Class> getGenericClass(Class> cls) { return getGenericClass(cls, 0); } /** * 获取实现接口上的泛型类型 * * @param cls 类型 * @param i 第几个泛型参数 * @return 实现接口的泛型 */ public static Class> getGenericClass(Class> cls, int i) { try { ParameterizedType parameterizedType = ((ParameterizedType) cls.getGenericInterfaces()[0]); Object genericClass = parameterizedType.getActualTypeArguments()[i]; if (genericClass instanceof ParameterizedType) { return (Class>) ((ParameterizedType) genericClass).getRawType(); } else if (genericClass instanceof GenericArrayType) { return (Class>) ((GenericArrayType) genericClass).getGenericComponentType(); } else { return (Class>) genericClass; } } catch (Throwable e) { throw new IllegalArgumentException(cls.getName() + " generic type undefined!", e); } } /** *
* get method name. "void do(int)", "void do()", "int do(java.lang.String,boolean)" * ** * @param m method. * @return name. */ public static String getName(final Method m) { StringBuilder ret = new StringBuilder(); ret.append(getName(m.getReturnType())).append(' '); ret.append(m.getName()).append('('); Class>[] parameterTypes = m.getParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) { if (i > 0) ret.append(','); ret.append(getName(parameterTypes[i])); } ret.append(')'); return ret.toString(); } /** * 获取一个方法的展示label * * @param methodName 方法名 * @param parameterTypes 参数 * @return 展示label */ public static String getSignature(String methodName, Class>[] parameterTypes) { StringBuilder sb = new StringBuilder(methodName); sb.append("("); if (parameterTypes != null && parameterTypes.length > 0) { boolean first = true; for (Class> type : parameterTypes) { if (first) { first = false; } else { sb.append(","); } sb.append(type.getName()); } } sb.append(")"); return sb.toString(); } /** *
* get constructor name. "()", "(java.lang.String,int)" ** * @param c constructor. * @return name. */ public static String getName(final Constructor> c) { StringBuilder ret = new StringBuilder("("); Class>[] parameterTypes = c.getParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) { if (i > 0) ret.append(','); ret.append(getName(parameterTypes[i])); } ret.append(')'); return ret.toString(); } /** *
* get class desc. * boolean[].class => "[Z" * Object.class => "Ljava/lang/Object;" * 获取类型的虚拟机表示形式 * ** * @param c class. * @return desc. */ public static String getDesc(Class> c) { StringBuilder ret = new StringBuilder(); while (c.isArray()) { ret.append('['); c = c.getComponentType(); } if (c.isPrimitive()) { String t = c.getName(); if ("void".equals(t)) ret.append(JVM_VOID); else if ("boolean".equals(t)) ret.append(JVM_BOOLEAN); else if ("byte".equals(t)) ret.append(JVM_BYTE); else if ("char".equals(t)) ret.append(JVM_CHAR); else if ("double".equals(t)) ret.append(JVM_DOUBLE); else if ("float".equals(t)) ret.append(JVM_FLOAT); else if ("int".equals(t)) ret.append(JVM_INT); else if ("long".equals(t)) ret.append(JVM_LONG); else if ("short".equals(t)) ret.append(JVM_SHORT); } else { ret.append('L'); ret.append(c.getName().replace('.', '/')); ret.append(';'); } return ret.toString(); } /** *
* get class array desc. * [int.class, boolean[].class, Object.class] => "I[ZLjava/lang/Object;" ** * @param cs class array. * @return desc. */ public static String getDesc(final Class>[] cs) { if (cs.length == 0) return ""; StringBuilder sb = new StringBuilder(64); for (Class> c : cs) sb.append(getDesc(c)); return sb.toString(); } /** *
* get method desc. * int do(int arg1) => "do(I)I" * void do(String arg1,boolean arg2) => "do(Ljava/lang/String;Z)V" ** * @param m method. * @return desc. */ public static String getDesc(final Method m) { StringBuilder ret = new StringBuilder(m.getName()).append('('); Class>[] parameterTypes = m.getParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) ret.append(getDesc(parameterTypes[i])); ret.append(')').append(getDesc(m.getReturnType())); return ret.toString(); } /** *
* get constructor desc. * public A() ==> "()V" * public A(String, int) ==> "(Ljava/lang/String;I)V" ** * @param c constructor. * @return desc */ public static String getDesc(final Constructor> c) { StringBuilder ret = new StringBuilder("("); Class>[] parameterTypes = c.getParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) ret.append(getDesc(parameterTypes[i])); ret.append(')').append('V'); return ret.toString(); } /** *
* get method desc. "(I)I", "()V", "(Ljava/lang/String;Z)V" ** * @param m method. * @return desc. */ public static String getDescWithoutMethodName(Method m) { StringBuilder ret = new StringBuilder(); ret.append('('); Class>[] parameterTypes = m.getParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) ret.append(getDesc(parameterTypes[i])); ret.append(')').append(getDesc(m.getReturnType())); return ret.toString(); } /** *
* name to desc. java.util.Map[][] => "[[Ljava/util/Map;" ** * @param name name. * @return desc. */ public static String name2desc(String name) { StringBuilder sb = new StringBuilder(); int c = 0, index = name.indexOf('['); if (index > 0) { c = (name.length() - index) / 2; name = name.substring(0, index); } while (c-- > 0) sb.append("["); if ("void".equals(name)) sb.append(JVM_VOID); else if ("boolean".equals(name)) sb.append(JVM_BOOLEAN); else if ("byte".equals(name)) sb.append(JVM_BYTE); else if ("char".equals(name)) sb.append(JVM_CHAR); else if ("double".equals(name)) sb.append(JVM_DOUBLE); else if ("float".equals(name)) sb.append(JVM_FLOAT); else if ("int".equals(name)) sb.append(JVM_INT); else if ("long".equals(name)) sb.append(JVM_LONG); else if ("short".equals(name)) sb.append(JVM_SHORT); else sb.append('L').append(name.replace('.', '/')).append(';'); return sb.toString(); } /** *
* desc to name. * "[[I" => "int[][]" ** * @param desc desc. * @return name. */ public static String desc2name(String desc) { StringBuilder sb = new StringBuilder(); int c = desc.lastIndexOf('[') + 1; if (desc.length() == c + 1) { switch (desc.charAt(c)) { case JVM_VOID: { sb.append("void"); break; } case JVM_BOOLEAN: { sb.append("boolean"); break; } case JVM_BYTE: { sb.append("byte"); break; } case JVM_CHAR: { sb.append("char"); break; } case JVM_DOUBLE: { sb.append("double"); break; } case JVM_FLOAT: { sb.append("float"); break; } case JVM_INT: { sb.append("int"); break; } case JVM_LONG: { sb.append("long"); break; } case JVM_SHORT: { sb.append("short"); break; } default: throw new RuntimeException(); } } else { sb.append(desc.substring(c + 1, desc.length() - 1).replace('/', '.')); } while (c-- > 0) sb.append("[]"); return sb.toString(); } /** *
* 根据类名加载一个类型 * * "boolean" => boolean.class * "java.common.Map[][]" => java.common.Map[][].class ** * @param name 类名 * @return 类型 */ public static Class> forName(String name) { try { return name2class(name); } catch (ClassNotFoundException e) { throw new IllegalStateException("Not found class " + name + ", cause: " + e.getMessage(), e); } } /** * name to class. "boolean" => boolean.class "java.common.Map[][]" => java.common.Map[][].class * * @param name name. * @return Class instance. */ public static Class> name2class(String name) throws ClassNotFoundException { return null; } /** * name to class. "boolean" => boolean.class "java.common.Map[][]" => java.common.Map[][].class * * @param cl ClassLoader instance. * @param name name. * @return Class instance. */ private static Class> name2class(ClassLoader cl, String name) throws ClassNotFoundException { return null; } /** *
* desc to class. * "[Z" => boolean[].class * "[[Ljava/common/Map;" => java.common.Map[][].class ** * @param desc desc. * @return Class instance. * @throws ClassNotFoundException */ public static Class> desc2class(String desc) throws ClassNotFoundException { return null; } /** * desc to class. "[Z" => boolean[].class "[[Ljava/common/Map;" => java.common.Map[][].class * * @param cl ClassLoader instance. * @param desc desc. * @return Class instance. * @throws ClassNotFoundException */ private static Class> desc2class(ClassLoader cl, String desc) throws ClassNotFoundException { return null; } /** * get class array instance. * * @param desc desc. * @return Class class array. * @throws ClassNotFoundException */ public static Class>[] desc2classArray(String desc) throws ClassNotFoundException { return null; } /** * get class array instance. * * @param cl ClassLoader instance. * @param desc desc. * @return Class[] class array. * @throws ClassNotFoundException */ private static Class>[] desc2classArray(ClassLoader cl, String desc) throws ClassNotFoundException { if (desc.length() == 0) return EMPTY_CLASS_ARRAY; List
* 根据方法名称和参数类型名查找Method ** * @param clazz 类型 * @param methodName 方法名 * @param parameterTypes 参数 * @return method * @throws NoSuchMethodException * @throws ClassNotFoundException */ public static Method findMethodByMethodSignature(Class> clazz, String methodName, String[] parameterTypes) throws NoSuchMethodException, ClassNotFoundException { String signature = methodName; if (parameterTypes != null && parameterTypes.length > 0) { signature = methodName + org.apache.commons.lang.StringUtils.join(parameterTypes); } Method method = Signature_METHODS_CACHE.get(signature); if (method != null) { return method; } if (parameterTypes == null) { List
* 根据方法名称和参数类型名查找Method,没有参数的方法 ** * @param clazz 类型 * @param methodName 方法名 * @return 方法 * @throws NoSuchMethodException * @throws ClassNotFoundException */ public static Method findMethodByMethodName(Class> clazz, String methodName) throws NoSuchMethodException, ClassNotFoundException { return findMethodByMethodSignature(clazz, methodName, null); } /** * 获取一个有参数的构造函数 * * @param clazz 类型 * @param paramType 参数类型 * @return 构造函数 * @throws NoSuchMethodException */ public static Constructor> findConstructor(Class> clazz, Class> paramType) throws NoSuchMethodException { Constructor> targetConstructor; try { targetConstructor = clazz.getConstructor(new Class>[]{paramType}); } catch (NoSuchMethodException e) { targetConstructor = null; Constructor>[] constructors = clazz.getConstructors(); for (Constructor> constructor : constructors) { if (Modifier.isPublic(constructor.getModifiers()) && constructor.getParameterTypes().length == 1 && constructor.getParameterTypes()[0].isAssignableFrom(paramType)) { targetConstructor = constructor; break; } } if (targetConstructor == null) { throw e; } } return targetConstructor; } /** * 当前实例是否实现了对应的接口 * * @param obj 实例 * @param interfaceClazzName 接口 * @return true表示实现了 */ public static boolean isInstance(Object obj, String interfaceClazzName) { for (Class> clazz = obj.getClass(); clazz != null && !clazz.equals(Object.class); clazz = clazz .getSuperclass()) { Class>[] interfaces = clazz.getInterfaces(); for (Class> itf : interfaces) { if (itf.getName().equals(interfaceClazzName)) { return true; } } } return false; } /** * 获取一个默认类型的默认对象 * * @param returnType 类型 * @return 默认对象 */ public static Object getEmptyObject(Class> returnType) { return getEmptyObject(returnType, new HashMap
© 2015 - 2025 Weber Informatics LLC | Privacy Policy