首页

关于alibaba的dubbo源码包中ReflectUtils反射工具类对类及方法的通用处理

标签:alibaba,dubbo,ReflectUtils,反射工具类     发布时间:2018-06-19   

一、前言

关于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@}