一、前言
关于alibaba的dubbo源码包com.alibaba.dubbo.common.utils.ReflectUtils反射工具类,对class类、类Method方法、类的Constructor容器常用处理,详情参见源码说明。
二、源码说明
package com.alibaba.dubbo.common.utils;@b@@b@import javassist.CtClass;@b@import javassist.CtConstructor;@b@import javassist.CtMethod;@b@import javassist.NotFoundException;@b@@b@import java.lang.reflect.Array;@b@import java.lang.reflect.Constructor;@b@import java.lang.reflect.Field;@b@import java.lang.reflect.GenericArrayType;@b@import java.lang.reflect.Method;@b@import java.lang.reflect.Modifier;@b@import java.lang.reflect.ParameterizedType;@b@import java.net.URL;@b@import java.security.CodeSource;@b@import java.security.ProtectionDomain;@b@import java.util.ArrayList;@b@import java.util.Date;@b@import java.util.HashMap;@b@import java.util.HashSet;@b@import java.util.List;@b@import java.util.Map;@b@import java.util.concurrent.ConcurrentHashMap;@b@import java.util.concurrent.ConcurrentMap;@b@import java.util.regex.Matcher;@b@import java.util.regex.Pattern;@b@@b@/**@b@ * ReflectUtils@b@ */@b@public final class ReflectUtils {@b@@b@ /**@b@ * void(V).@b@ */@b@ public static final char JVM_VOID = 'V';@b@@b@ /**@b@ * boolean(Z).@b@ */@b@ public static final char JVM_BOOLEAN = 'Z';@b@@b@ /**@b@ * byte(B).@b@ */@b@ public static final char JVM_BYTE = 'B';@b@@b@ /**@b@ * char(C).@b@ */@b@ public static final char JVM_CHAR = 'C';@b@@b@ /**@b@ * double(D).@b@ */@b@ public static final char JVM_DOUBLE = 'D';@b@@b@ /**@b@ * float(F).@b@ */@b@ public static final char JVM_FLOAT = 'F';@b@@b@ /**@b@ * int(I).@b@ */@b@ public static final char JVM_INT = 'I';@b@@b@ /**@b@ * long(J).@b@ */@b@ public static final char JVM_LONG = 'J';@b@@b@ /**@b@ * short(S).@b@ */@b@ public static final char JVM_SHORT = 'S';@b@@b@ public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];@b@@b@ public static final String JAVA_IDENT_REGEX = "(?:[_$a-zA-Z][_$a-zA-Z0-9]*)";@b@@b@ public static final String JAVA_NAME_REGEX = "(?:" + JAVA_IDENT_REGEX + "(?:\\." + JAVA_IDENT_REGEX + ")*)";@b@@b@ public static final String CLASS_DESC = "(?:L" + JAVA_IDENT_REGEX + "(?:\\/" + JAVA_IDENT_REGEX + ")*;)";@b@@b@ public static final String ARRAY_DESC = "(?:\\[+(?:(?:[VZBCDFIJS])|" + CLASS_DESC + "))";@b@@b@ public static final String DESC_REGEX = "(?:(?:[VZBCDFIJS])|" + CLASS_DESC + "|" + ARRAY_DESC + ")";@b@@b@ public static final Pattern DESC_PATTERN = Pattern.compile(DESC_REGEX);@b@@b@ public static final String METHOD_DESC_REGEX = "(?:(" + JAVA_IDENT_REGEX + ")?\\((" + DESC_REGEX + "*)\\)(" + DESC_REGEX + ")?)";@b@@b@ public static final Pattern METHOD_DESC_PATTERN = Pattern.compile(METHOD_DESC_REGEX);@b@@b@ public static final Pattern GETTER_METHOD_DESC_PATTERN = Pattern.compile("get([A-Z][_a-zA-Z0-9]*)\\(\\)(" + DESC_REGEX + ")");@b@@b@ public static final Pattern SETTER_METHOD_DESC_PATTERN = Pattern.compile("set([A-Z][_a-zA-Z0-9]*)\\((" + DESC_REGEX + ")\\)V");@b@@b@ public static final Pattern IS_HAS_CAN_METHOD_DESC_PATTERN = Pattern.compile("(?:is|has|can)([A-Z][_a-zA-Z0-9]*)\\(\\)Z");@b@@b@ private static final ConcurrentMap<String, Class<?>> DESC_CLASS_CACHE = new ConcurrentHashMap<String, Class<?>>();@b@@b@ private static final ConcurrentMap<String, Class<?>> NAME_CLASS_CACHE = new ConcurrentHashMap<String, Class<?>>();@b@@b@ private static final ConcurrentMap<String, Method> Signature_METHODS_CACHE = new ConcurrentHashMap<String, Method>();@b@@b@ private ReflectUtils() {@b@ }@b@@b@ public static boolean isPrimitives(Class<?> cls) {@b@ if (cls.isArray()) {@b@ return isPrimitive(cls.getComponentType());@b@ }@b@ return isPrimitive(cls);@b@ }@b@@b@ public static boolean isPrimitive(Class<?> cls) {@b@ return cls.isPrimitive() || cls == String.class || cls == Boolean.class || cls == Character.class@b@ || Number.class.isAssignableFrom(cls) || Date.class.isAssignableFrom(cls);@b@ }@b@@b@ public static Class<?> getBoxedClass(Class<?> c) {@b@ if (c == int.class)@b@ c = Integer.class;@b@ else if (c == boolean.class)@b@ c = Boolean.class;@b@ else if (c == long.class)@b@ c = Long.class;@b@ else if (c == float.class)@b@ c = Float.class;@b@ else if (c == double.class)@b@ c = Double.class;@b@ else if (c == char.class)@b@ c = Character.class;@b@ else if (c == byte.class)@b@ c = Byte.class;@b@ else if (c == short.class)@b@ c = Short.class;@b@ return c;@b@ }@b@@b@ /**@b@ * is compatible.@b@ *@b@ * @param c class.@b@ * @param o instance.@b@ * @return compatible or not.@b@ */@b@ public static boolean isCompatible(Class<?> c, Object o) {@b@ boolean pt = c.isPrimitive();@b@ if (o == null)@b@ return !pt;@b@@b@ if (pt) {@b@ if (c == int.class)@b@ c = Integer.class;@b@ else if (c == boolean.class)@b@ c = Boolean.class;@b@ else if (c == long.class)@b@ c = Long.class;@b@ else if (c == float.class)@b@ c = Float.class;@b@ else if (c == double.class)@b@ c = Double.class;@b@ else if (c == char.class)@b@ c = Character.class;@b@ else if (c == byte.class)@b@ c = Byte.class;@b@ else if (c == short.class)@b@ c = Short.class;@b@ }@b@ if (c == o.getClass())@b@ return true;@b@ return c.isInstance(o);@b@ }@b@@b@ /**@b@ * is compatible.@b@ *@b@ * @param cs class array.@b@ * @param os object array.@b@ * @return compatible or not.@b@ */@b@ public static boolean isCompatible(Class<?>[] cs, Object[] os) {@b@ int len = cs.length;@b@ if (len != os.length) return false;@b@ if (len == 0) return true;@b@ for (int i = 0; i < len; i++)@b@ if (!isCompatible(cs[i], os[i])) return false;@b@ return true;@b@ }@b@@b@ public static String getCodeBase(Class<?> cls) {@b@ if (cls == null)@b@ return null;@b@ ProtectionDomain domain = cls.getProtectionDomain();@b@ if (domain == null)@b@ return null;@b@ CodeSource source = domain.getCodeSource();@b@ if (source == null)@b@ return null;@b@ URL location = source.getLocation();@b@ if (location == null)@b@ return null;@b@ return location.getFile();@b@ }@b@@b@ /**@b@ * get name.@b@ * java.lang.Object[][].class => "java.lang.Object[][]"@b@ *@b@ * @param c class.@b@ * @return name.@b@ */@b@ public static String getName(Class<?> c) {@b@ if (c.isArray()) {@b@ StringBuilder sb = new StringBuilder();@b@ do {@b@ sb.append("[]");@b@ c = c.getComponentType();@b@ }@b@ while (c.isArray());@b@@b@ return c.getName() + sb.toString();@b@ }@b@ return c.getName();@b@ }@b@@b@ public static Class<?> getGenericClass(Class<?> cls) {@b@ return getGenericClass(cls, 0);@b@ }@b@@b@ public static Class<?> getGenericClass(Class<?> cls, int i) {@b@ try {@b@ ParameterizedType parameterizedType = ((ParameterizedType) cls.getGenericInterfaces()[0]);@b@ Object genericClass = parameterizedType.getActualTypeArguments()[i];@b@ if (genericClass instanceof ParameterizedType) { // handle nested generic type@b@ return (Class<?>) ((ParameterizedType) genericClass).getRawType();@b@ } else if (genericClass instanceof GenericArrayType) { // handle array generic type@b@ return (Class<?>) ((GenericArrayType) genericClass).getGenericComponentType();@b@ } else if (((Class) genericClass).isArray()) {@b@ // Requires JDK 7 or higher, Foo<int[]> is no longer GenericArrayType@b@ return ((Class) genericClass).getComponentType();@b@ } else {@b@ return (Class<?>) genericClass;@b@ }@b@ } catch (Throwable e) {@b@ throw new IllegalArgumentException(cls.getName()@b@ + " generic type undefined!", e);@b@ }@b@ }@b@@b@ /**@b@ * get method name.@b@ * "void do(int)", "void do()", "int do(java.lang.String,boolean)"@b@ *@b@ * @param m method.@b@ * @return name.@b@ */@b@ public static String getName(final Method m) {@b@ StringBuilder ret = new StringBuilder();@b@ ret.append(getName(m.getReturnType())).append(' ');@b@ ret.append(m.getName()).append('(');@b@ Class<?>[] parameterTypes = m.getParameterTypes();@b@ for (int i = 0; i < parameterTypes.length; i++) {@b@ if (i > 0)@b@ ret.append(',');@b@ ret.append(getName(parameterTypes[i]));@b@ }@b@ ret.append(')');@b@ return ret.toString();@b@ }@b@@b@ public static String getSignature(String methodName, Class<?>[] parameterTypes) {@b@ StringBuilder sb = new StringBuilder(methodName);@b@ sb.append("(");@b@ if (parameterTypes != null && parameterTypes.length > 0) {@b@ boolean first = true;@b@ for (Class<?> type : parameterTypes) {@b@ if (first) {@b@ first = false;@b@ } else {@b@ sb.append(",");@b@ }@b@ sb.append(type.getName());@b@ }@b@ }@b@ sb.append(")");@b@ return sb.toString();@b@ }@b@@b@ /**@b@ * get constructor name.@b@ * "()", "(java.lang.String,int)"@b@ *@b@ * @param c constructor.@b@ * @return name.@b@ */@b@ public static String getName(final Constructor<?> c) {@b@ StringBuilder ret = new StringBuilder("(");@b@ Class<?>[] parameterTypes = c.getParameterTypes();@b@ for (int i = 0; i < parameterTypes.length; i++) {@b@ if (i > 0)@b@ ret.append(',');@b@ ret.append(getName(parameterTypes[i]));@b@ }@b@ ret.append(')');@b@ return ret.toString();@b@ }@b@@b@ /**@b@ * get class desc.@b@ * boolean[].class => "[Z"@b@ * Object.class => "Ljava/lang/Object;"@b@ *@b@ * @param c class.@b@ * @return desc.@b@ * @throws NotFoundException@b@ */@b@ public static String getDesc(Class<?> c) {@b@ StringBuilder ret = new StringBuilder();@b@@b@ while (c.isArray()) {@b@ ret.append('[');@b@ c = c.getComponentType();@b@ }@b@@b@ if (c.isPrimitive()) {@b@ String t = c.getName();@b@ if ("void".equals(t)) ret.append(JVM_VOID);@b@ else if ("boolean".equals(t)) ret.append(JVM_BOOLEAN);@b@ else if ("byte".equals(t)) ret.append(JVM_BYTE);@b@ else if ("char".equals(t)) ret.append(JVM_CHAR);@b@ else if ("double".equals(t)) ret.append(JVM_DOUBLE);@b@ else if ("float".equals(t)) ret.append(JVM_FLOAT);@b@ else if ("int".equals(t)) ret.append(JVM_INT);@b@ else if ("long".equals(t)) ret.append(JVM_LONG);@b@ else if ("short".equals(t)) ret.append(JVM_SHORT);@b@ } else {@b@ ret.append('L');@b@ ret.append(c.getName().replace('.', '/'));@b@ ret.append(';');@b@ }@b@ return ret.toString();@b@ }@b@@b@ /**@b@ * get class array desc.@b@ * [int.class, boolean[].class, Object.class] => "I[ZLjava/lang/Object;"@b@ *@b@ * @param cs class array.@b@ * @return desc.@b@ * @throws NotFoundException@b@ */@b@ public static String getDesc(final Class<?>[] cs) {@b@ if (cs.length == 0)@b@ return "";@b@@b@ StringBuilder sb = new StringBuilder(64);@b@ for (Class<?> c : cs)@b@ sb.append(getDesc(c));@b@ return sb.toString();@b@ }@b@@b@ /**@b@ * get method desc.@b@ * int do(int arg1) => "do(I)I"@b@ * void do(String arg1,boolean arg2) => "do(Ljava/lang/String;Z)V"@b@ *@b@ * @param m method.@b@ * @return desc.@b@ */@b@ public static String getDesc(final Method m) {@b@ StringBuilder ret = new StringBuilder(m.getName()).append('(');@b@ Class<?>[] parameterTypes = m.getParameterTypes();@b@ for (int i = 0; i < parameterTypes.length; i++)@b@ ret.append(getDesc(parameterTypes[i]));@b@ ret.append(')').append(getDesc(m.getReturnType()));@b@ return ret.toString();@b@ }@b@@b@ /**@b@ * get constructor desc.@b@ * "()V", "(Ljava/lang/String;I)V"@b@ *@b@ * @param c constructor.@b@ * @return desc@b@ */@b@ public static String getDesc(final Constructor<?> c) {@b@ StringBuilder ret = new StringBuilder("(");@b@ Class<?>[] parameterTypes = c.getParameterTypes();@b@ for (int i = 0; i < parameterTypes.length; i++)@b@ ret.append(getDesc(parameterTypes[i]));@b@ ret.append(')').append('V');@b@ return ret.toString();@b@ }@b@@b@ /**@b@ * get method desc.@b@ * "(I)I", "()V", "(Ljava/lang/String;Z)V"@b@ *@b@ * @param m method.@b@ * @return desc.@b@ */@b@ public static String getDescWithoutMethodName(Method m) {@b@ StringBuilder ret = new StringBuilder();@b@ ret.append('(');@b@ Class<?>[] parameterTypes = m.getParameterTypes();@b@ for (int i = 0; i < parameterTypes.length; i++)@b@ ret.append(getDesc(parameterTypes[i]));@b@ ret.append(')').append(getDesc(m.getReturnType()));@b@ return ret.toString();@b@ }@b@@b@ /**@b@ * get class desc.@b@ * Object.class => "Ljava/lang/Object;"@b@ * boolean[].class => "[Z"@b@ *@b@ * @param c class.@b@ * @return desc.@b@ * @throws NotFoundException@b@ */@b@ public static String getDesc(final CtClass c) throws NotFoundException {@b@ StringBuilder ret = new StringBuilder();@b@ if (c.isArray()) {@b@ ret.append('[');@b@ ret.append(getDesc(c.getComponentType()));@b@ } else if (c.isPrimitive()) {@b@ String t = c.getName();@b@ if ("void".equals(t)) ret.append(JVM_VOID);@b@ else if ("boolean".equals(t)) ret.append(JVM_BOOLEAN);@b@ else if ("byte".equals(t)) ret.append(JVM_BYTE);@b@ else if ("char".equals(t)) ret.append(JVM_CHAR);@b@ else if ("double".equals(t)) ret.append(JVM_DOUBLE);@b@ else if ("float".equals(t)) ret.append(JVM_FLOAT);@b@ else if ("int".equals(t)) ret.append(JVM_INT);@b@ else if ("long".equals(t)) ret.append(JVM_LONG);@b@ else if ("short".equals(t)) ret.append(JVM_SHORT);@b@ } else {@b@ ret.append('L');@b@ ret.append(c.getName().replace('.', '/'));@b@ ret.append(';');@b@ }@b@ return ret.toString();@b@ }@b@@b@ /**@b@ * get method desc.@b@ * "do(I)I", "do()V", "do(Ljava/lang/String;Z)V"@b@ *@b@ * @param m method.@b@ * @return desc.@b@ */@b@ public static String getDesc(final CtMethod m) throws NotFoundException {@b@ StringBuilder ret = new StringBuilder(m.getName()).append('(');@b@ CtClass[] parameterTypes = m.getParameterTypes();@b@ for (int i = 0; i < parameterTypes.length; i++)@b@ ret.append(getDesc(parameterTypes[i]));@b@ ret.append(')').append(getDesc(m.getReturnType()));@b@ return ret.toString();@b@ }@b@@b@ /**@b@ * get constructor desc.@b@ * "()V", "(Ljava/lang/String;I)V"@b@ *@b@ * @param c constructor.@b@ * @return desc@b@ */@b@ public static String getDesc(final CtConstructor c) throws NotFoundException {@b@ StringBuilder ret = new StringBuilder("(");@b@ CtClass[] parameterTypes = c.getParameterTypes();@b@ for (int i = 0; i < parameterTypes.length; i++)@b@ ret.append(getDesc(parameterTypes[i]));@b@ ret.append(')').append('V');@b@ return ret.toString();@b@ }@b@@b@ /**@b@ * get method desc.@b@ * "(I)I", "()V", "(Ljava/lang/String;Z)V".@b@ *@b@ * @param m method.@b@ * @return desc.@b@ */@b@ public static String getDescWithoutMethodName(final CtMethod m) throws NotFoundException {@b@ StringBuilder ret = new StringBuilder();@b@ ret.append('(');@b@ CtClass[] parameterTypes = m.getParameterTypes();@b@ for (int i = 0; i < parameterTypes.length; i++)@b@ ret.append(getDesc(parameterTypes[i]));@b@ ret.append(')').append(getDesc(m.getReturnType()));@b@ return ret.toString();@b@ }@b@@b@ /**@b@ * name to desc.@b@ * java.util.Map[][] => "[[Ljava/util/Map;"@b@ *@b@ * @param name name.@b@ * @return desc.@b@ */@b@ public static String name2desc(String name) {@b@ StringBuilder sb = new StringBuilder();@b@ int c = 0, index = name.indexOf('[');@b@ if (index > 0) {@b@ c = (name.length() - index) / 2;@b@ name = name.substring(0, index);@b@ }@b@ while (c-- > 0) sb.append("[");@b@ if ("void".equals(name)) sb.append(JVM_VOID);@b@ else if ("boolean".equals(name)) sb.append(JVM_BOOLEAN);@b@ else if ("byte".equals(name)) sb.append(JVM_BYTE);@b@ else if ("char".equals(name)) sb.append(JVM_CHAR);@b@ else if ("double".equals(name)) sb.append(JVM_DOUBLE);@b@ else if ("float".equals(name)) sb.append(JVM_FLOAT);@b@ else if ("int".equals(name)) sb.append(JVM_INT);@b@ else if ("long".equals(name)) sb.append(JVM_LONG);@b@ else if ("short".equals(name)) sb.append(JVM_SHORT);@b@ else sb.append('L').append(name.replace('.', '/')).append(';');@b@ return sb.toString();@b@ }@b@@b@ /**@b@ * desc to name.@b@ * "[[I" => "int[][]"@b@ *@b@ * @param desc desc.@b@ * @return name.@b@ */@b@ public static String desc2name(String desc) {@b@ StringBuilder sb = new StringBuilder();@b@ int c = desc.lastIndexOf('[') + 1;@b@ if (desc.length() == c + 1) {@b@ switch (desc.charAt(c)) {@b@ case JVM_VOID: {@b@ sb.append("void");@b@ break;@b@ }@b@ case JVM_BOOLEAN: {@b@ sb.append("boolean");@b@ break;@b@ }@b@ case JVM_BYTE: {@b@ sb.append("byte");@b@ break;@b@ }@b@ case JVM_CHAR: {@b@ sb.append("char");@b@ break;@b@ }@b@ case JVM_DOUBLE: {@b@ sb.append("double");@b@ break;@b@ }@b@ case JVM_FLOAT: {@b@ sb.append("float");@b@ break;@b@ }@b@ case JVM_INT: {@b@ sb.append("int");@b@ break;@b@ }@b@ case JVM_LONG: {@b@ sb.append("long");@b@ break;@b@ }@b@ case JVM_SHORT: {@b@ sb.append("short");@b@ break;@b@ }@b@ default:@b@ throw new RuntimeException();@b@ }@b@ } else {@b@ sb.append(desc.substring(c + 1, desc.length() - 1).replace('/', '.'));@b@ }@b@ while (c-- > 0) sb.append("[]");@b@ return sb.toString();@b@ }@b@@b@ public static Class<?> forName(String name) {@b@ try {@b@ return name2class(name);@b@ } catch (ClassNotFoundException e) {@b@ throw new IllegalStateException("Not found class " + name + ", cause: " + e.getMessage(), e);@b@ }@b@ }@b@@b@ /**@b@ * name to class.@b@ * "boolean" => boolean.class@b@ * "java.util.Map[][]" => java.util.Map[][].class@b@ *@b@ * @param name name.@b@ * @return Class instance.@b@ */@b@ public static Class<?> name2class(String name) throws ClassNotFoundException {@b@ return name2class(ClassHelper.getClassLoader(), name);@b@ }@b@@b@ /**@b@ * name to class.@b@ * "boolean" => boolean.class@b@ * "java.util.Map[][]" => java.util.Map[][].class@b@ *@b@ * @param cl ClassLoader instance.@b@ * @param name name.@b@ * @return Class instance.@b@ */@b@ private static Class<?> name2class(ClassLoader cl, String name) throws ClassNotFoundException {@b@ int c = 0, index = name.indexOf('[');@b@ if (index > 0) {@b@ c = (name.length() - index) / 2;@b@ name = name.substring(0, index);@b@ }@b@ if (c > 0) {@b@ StringBuilder sb = new StringBuilder();@b@ while (c-- > 0)@b@ sb.append("[");@b@@b@ if ("void".equals(name)) sb.append(JVM_VOID);@b@ else if ("boolean".equals(name)) sb.append(JVM_BOOLEAN);@b@ else if ("byte".equals(name)) sb.append(JVM_BYTE);@b@ else if ("char".equals(name)) sb.append(JVM_CHAR);@b@ else if ("double".equals(name)) sb.append(JVM_DOUBLE);@b@ else if ("float".equals(name)) sb.append(JVM_FLOAT);@b@ else if ("int".equals(name)) sb.append(JVM_INT);@b@ else if ("long".equals(name)) sb.append(JVM_LONG);@b@ else if ("short".equals(name)) sb.append(JVM_SHORT);@b@ else sb.append('L').append(name).append(';'); // "java.lang.Object" ==> "Ljava.lang.Object;"@b@ name = sb.toString();@b@ } else {@b@ if ("void".equals(name)) return void.class;@b@ else if ("boolean".equals(name)) return boolean.class;@b@ else if ("byte".equals(name)) return byte.class;@b@ else if ("char".equals(name)) return char.class;@b@ else if ("double".equals(name)) return double.class;@b@ else if ("float".equals(name)) return float.class;@b@ else if ("int".equals(name)) return int.class;@b@ else if ("long".equals(name)) return long.class;@b@ else if ("short".equals(name)) return short.class;@b@ }@b@@b@ if (cl == null)@b@ cl = ClassHelper.getClassLoader();@b@ Class<?> clazz = NAME_CLASS_CACHE.get(name);@b@ if (clazz == null) {@b@ clazz = Class.forName(name, true, cl);@b@ NAME_CLASS_CACHE.put(name, clazz);@b@ }@b@ return clazz;@b@ }@b@@b@ /**@b@ * desc to class.@b@ * "[Z" => boolean[].class@b@ * "[[Ljava/util/Map;" => java.util.Map[][].class@b@ *@b@ * @param desc desc.@b@ * @return Class instance.@b@ * @throws ClassNotFoundException@b@ */@b@ public static Class<?> desc2class(String desc) throws ClassNotFoundException {@b@ return desc2class(ClassHelper.getClassLoader(), desc);@b@ }@b@@b@ /**@b@ * desc to class.@b@ * "[Z" => boolean[].class@b@ * "[[Ljava/util/Map;" => java.util.Map[][].class@b@ *@b@ * @param cl ClassLoader instance.@b@ * @param desc desc.@b@ * @return Class instance.@b@ * @throws ClassNotFoundException@b@ */@b@ private static Class<?> desc2class(ClassLoader cl, String desc) throws ClassNotFoundException {@b@ switch (desc.charAt(0)) {@b@ case JVM_VOID:@b@ return void.class;@b@ case JVM_BOOLEAN:@b@ return boolean.class;@b@ case JVM_BYTE:@b@ return byte.class;@b@ case JVM_CHAR:@b@ return char.class;@b@ case JVM_DOUBLE:@b@ return double.class;@b@ case JVM_FLOAT:@b@ return float.class;@b@ case JVM_INT:@b@ return int.class;@b@ case JVM_LONG:@b@ return long.class;@b@ case JVM_SHORT:@b@ return short.class;@b@ case 'L':@b@ desc = desc.substring(1, desc.length() - 1).replace('/', '.'); // "Ljava/lang/Object;" ==> "java.lang.Object"@b@ break;@b@ case '[':@b@ desc = desc.replace('/', '.'); // "[[Ljava/lang/Object;" ==> "[[Ljava.lang.Object;"@b@ break;@b@ default:@b@ throw new ClassNotFoundException("Class not found: " + desc);@b@ }@b@@b@ if (cl == null)@b@ cl = ClassHelper.getClassLoader();@b@ Class<?> clazz = DESC_CLASS_CACHE.get(desc);@b@ if (clazz == null) {@b@ clazz = Class.forName(desc, true, cl);@b@ DESC_CLASS_CACHE.put(desc, clazz);@b@ }@b@ return clazz;@b@ }@b@@b@ /**@b@ * get class array instance.@b@ *@b@ * @param desc desc.@b@ * @return Class class array.@b@ * @throws ClassNotFoundException@b@ */@b@ public static Class<?>[] desc2classArray(String desc) throws ClassNotFoundException {@b@ Class<?>[] ret = desc2classArray(ClassHelper.getClassLoader(), desc);@b@ return ret;@b@ }@b@@b@ /**@b@ * get class array instance.@b@ *@b@ * @param cl ClassLoader instance.@b@ * @param desc desc.@b@ * @return Class[] class array.@b@ * @throws ClassNotFoundException@b@ */@b@ private static Class<?>[] desc2classArray(ClassLoader cl, String desc) throws ClassNotFoundException {@b@ if (desc.length() == 0)@b@ return EMPTY_CLASS_ARRAY;@b@@b@ List<Class<?>> cs = new ArrayList<Class<?>>();@b@ Matcher m = DESC_PATTERN.matcher(desc);@b@ while (m.find())@b@ cs.add(desc2class(cl, m.group()));@b@ return cs.toArray(EMPTY_CLASS_ARRAY);@b@ }@b@@b@ /**@b@ * Find method from method signature@b@ *@b@ * @param clazz Target class to find method@b@ * @param methodName Method signature, e.g.: method1(int, String). It is allowed to provide method name only, e.g.: method2@b@ * @return target method@b@ * @throws NoSuchMethodException@b@ * @throws ClassNotFoundException@b@ * @throws IllegalStateException when multiple methods are found (overridden method when parameter info is not provided)@b@ */@b@ public static Method findMethodByMethodSignature(Class<?> clazz, String methodName, String[] parameterTypes)@b@ throws NoSuchMethodException, ClassNotFoundException {@b@ String signature = clazz.getName() + "." + methodName;@b@ if (parameterTypes != null && parameterTypes.length > 0) {@b@ signature += StringUtils.join(parameterTypes);@b@ }@b@ Method method = Signature_METHODS_CACHE.get(signature);@b@ if (method != null) {@b@ return method;@b@ }@b@ if (parameterTypes == null) {@b@ List<Method> finded = new ArrayList<Method>();@b@ for (Method m : clazz.getMethods()) {@b@ if (m.getName().equals(methodName)) {@b@ finded.add(m);@b@ }@b@ }@b@ if (finded.isEmpty()) {@b@ throw new NoSuchMethodException("No such method " + methodName + " in class " + clazz);@b@ }@b@ if (finded.size() > 1) {@b@ String msg = String.format("Not unique method for method name(%s) in class(%s), find %d methods.",@b@ methodName, clazz.getName(), finded.size());@b@ throw new IllegalStateException(msg);@b@ }@b@ method = finded.get(0);@b@ } else {@b@ Class<?>[] types = new Class<?>[parameterTypes.length];@b@ for (int i = 0; i < parameterTypes.length; i++) {@b@ types[i] = ReflectUtils.name2class(parameterTypes[i]);@b@ }@b@ method = clazz.getMethod(methodName, types);@b@@b@ }@b@ Signature_METHODS_CACHE.put(signature, method);@b@ return method;@b@ }@b@@b@ public static Method findMethodByMethodName(Class<?> clazz, String methodName)@b@ throws NoSuchMethodException, ClassNotFoundException {@b@ return findMethodByMethodSignature(clazz, methodName, null);@b@ }@b@@b@ public static Constructor<?> findConstructor(Class<?> clazz, Class<?> paramType) throws NoSuchMethodException {@b@ Constructor<?> targetConstructor;@b@ try {@b@ targetConstructor = clazz.getConstructor(new Class<?>[]{paramType});@b@ } catch (NoSuchMethodException e) {@b@ targetConstructor = null;@b@ Constructor<?>[] constructors = clazz.getConstructors();@b@ for (Constructor<?> constructor : constructors) {@b@ if (Modifier.isPublic(constructor.getModifiers())@b@ && constructor.getParameterTypes().length == 1@b@ && constructor.getParameterTypes()[0].isAssignableFrom(paramType)) {@b@ targetConstructor = constructor;@b@ break;@b@ }@b@ }@b@ if (targetConstructor == null) {@b@ throw e;@b@ }@b@ }@b@ return targetConstructor;@b@ }@b@@b@ /**@b@ * Check if one object is the implementation for a given interface.@b@ * <p>@b@ * This method will not trigger classloading for the given interface, therefore it will not lead to error when@b@ * the given interface is not visible by the classloader@b@ *@b@ * @param obj Object to examine@b@ * @param interfaceClazzName The given interface@b@ * @return true if the object implements the given interface, otherwise return false@b@ */@b@ public static boolean isInstance(Object obj, String interfaceClazzName) {@b@ for (Class<?> clazz = obj.getClass();@b@ clazz != null && !clazz.equals(Object.class);@b@ clazz = clazz.getSuperclass()) {@b@ Class<?>[] interfaces = clazz.getInterfaces();@b@ for (Class<?> itf : interfaces) {@b@ if (itf.getName().equals(interfaceClazzName)) {@b@ return true;@b@ }@b@ }@b@ }@b@ return false;@b@ }@b@@b@ public static Object getEmptyObject(Class<?> returnType) {@b@ return getEmptyObject(returnType, new HashMap<Class<?>, Object>(), 0);@b@ }@b@@b@ private static Object getEmptyObject(Class<?> returnType, Map<Class<?>, Object> emptyInstances, int level) {@b@ if (level > 2)@b@ return null;@b@ if (returnType == null) {@b@ return null;@b@ } else if (returnType == boolean.class || returnType == Boolean.class) {@b@ return false;@b@ } else if (returnType == char.class || returnType == Character.class) {@b@ return '\0';@b@ } else if (returnType == byte.class || returnType == Byte.class) {@b@ return (byte) 0;@b@ } else if (returnType == short.class || returnType == Short.class) {@b@ return (short) 0;@b@ } else if (returnType == int.class || returnType == Integer.class) {@b@ return 0;@b@ } else if (returnType == long.class || returnType == Long.class) {@b@ return 0L;@b@ } else if (returnType == float.class || returnType == Float.class) {@b@ return 0F;@b@ } else if (returnType == double.class || returnType == Double.class) {@b@ return 0D;@b@ } else if (returnType.isArray()) {@b@ return Array.newInstance(returnType.getComponentType(), 0);@b@ } else if (returnType.isAssignableFrom(ArrayList.class)) {@b@ return new ArrayList<Object>(0);@b@ } else if (returnType.isAssignableFrom(HashSet.class)) {@b@ return new HashSet<Object>(0);@b@ } else if (returnType.isAssignableFrom(HashMap.class)) {@b@ return new HashMap<Object, Object>(0);@b@ } else if (String.class.equals(returnType)) {@b@ return "";@b@ } else if (!returnType.isInterface()) {@b@ try {@b@ Object value = emptyInstances.get(returnType);@b@ if (value == null) {@b@ value = returnType.newInstance();@b@ emptyInstances.put(returnType, value);@b@ }@b@ Class<?> cls = value.getClass();@b@ while (cls != null && cls != Object.class) {@b@ Field[] fields = cls.getDeclaredFields();@b@ for (Field field : fields) {@b@ Object property = getEmptyObject(field.getType(), emptyInstances, level + 1);@b@ if (property != null) {@b@ try {@b@ if (!field.isAccessible()) {@b@ field.setAccessible(true);@b@ }@b@ field.set(value, property);@b@ } catch (Throwable e) {@b@ }@b@ }@b@ }@b@ cls = cls.getSuperclass();@b@ }@b@ return value;@b@ } catch (Throwable e) {@b@ return null;@b@ }@b@ } else {@b@ return null;@b@ }@b@ }@b@@b@ public static boolean isBeanPropertyReadMethod(Method method) {@b@ return method != null@b@ && Modifier.isPublic(method.getModifiers())@b@ && !Modifier.isStatic(method.getModifiers())@b@ && method.getReturnType() != void.class@b@ && method.getDeclaringClass() != Object.class@b@ && method.getParameterTypes().length == 0@b@ && ((method.getName().startsWith("get") && method.getName().length() > 3)@b@ || (method.getName().startsWith("is") && method.getName().length() > 2));@b@ }@b@@b@ public static String getPropertyNameFromBeanReadMethod(Method method) {@b@ if (isBeanPropertyReadMethod(method)) {@b@ if (method.getName().startsWith("get")) {@b@ return method.getName().substring(3, 4).toLowerCase()@b@ + method.getName().substring(4);@b@ }@b@ if (method.getName().startsWith("is")) {@b@ return method.getName().substring(2, 3).toLowerCase()@b@ + method.getName().substring(3);@b@ }@b@ }@b@ return null;@b@ }@b@@b@ public static boolean isBeanPropertyWriteMethod(Method method) {@b@ return method != null@b@ && Modifier.isPublic(method.getModifiers())@b@ && !Modifier.isStatic(method.getModifiers())@b@ && method.getDeclaringClass() != Object.class@b@ && method.getParameterTypes().length == 1@b@ && method.getName().startsWith("set")@b@ && method.getName().length() > 3;@b@ }@b@@b@ public static String getPropertyNameFromBeanWriteMethod(Method method) {@b@ if (isBeanPropertyWriteMethod(method)) {@b@ return method.getName().substring(3, 4).toLowerCase()@b@ + method.getName().substring(4);@b@ }@b@ return null;@b@ }@b@@b@ public static boolean isPublicInstanceField(Field field) {@b@ return Modifier.isPublic(field.getModifiers())@b@ && !Modifier.isStatic(field.getModifiers())@b@ && !Modifier.isFinal(field.getModifiers())@b@ && !field.isSynthetic();@b@ }@b@@b@ public static Map<String, Field> getBeanPropertyFields(Class cl) {@b@ Map<String, Field> properties = new HashMap<String, Field>();@b@ for (; cl != null; cl = cl.getSuperclass()) {@b@ Field[] fields = cl.getDeclaredFields();@b@ for (Field field : fields) {@b@ if (Modifier.isTransient(field.getModifiers())@b@ || Modifier.isStatic(field.getModifiers())) {@b@ continue;@b@ }@b@@b@ field.setAccessible(true);@b@@b@ properties.put(field.getName(), field);@b@ }@b@ }@b@@b@ return properties;@b@ }@b@@b@ public static Map<String, Method> getBeanPropertyReadMethods(Class cl) {@b@ Map<String, Method> properties = new HashMap<String, Method>();@b@ for (; cl != null; cl = cl.getSuperclass()) {@b@ Method[] methods = cl.getDeclaredMethods();@b@ for (Method method : methods) {@b@ if (isBeanPropertyReadMethod(method)) {@b@ method.setAccessible(true);@b@ String property = getPropertyNameFromBeanReadMethod(method);@b@ properties.put(property, method);@b@ }@b@ }@b@ }@b@@b@ return properties;@b@ }@b@}