首页

关于alibaba的dubbo源码包中ClassHelper类对于优化基本数据类型不依赖类加载器获取class对象源码示例

标签:alibaba,dubbo,ClassHelper,类加载器,ClassLoader     发布时间:2018-06-23   

一、前言

关于alibaba的dubbo源码包com.alibaba.dubbo.common.utils.ClassHelper类对象处理类,除了实现基于类加载器获取对应类对象Class外,对于基本数据类型和数组直接匹配返回对应的数据类型,详情参见源码说明。

二、源码说明

package com.alibaba.dubbo.common.utils;@b@@b@import java.lang.reflect.Array;@b@import java.util.Arrays;@b@import java.util.HashMap;@b@import java.util.HashSet;@b@import java.util.Iterator;@b@import java.util.Map;@b@import java.util.Set;@b@@b@public class ClassHelper {@b@@b@    /**@b@     * Suffix for array class names: "[]"@b@     */@b@    public static final String ARRAY_SUFFIX = "[]";@b@    /**@b@     * Prefix for internal array class names: "[L"@b@     */@b@    private static final String INTERNAL_ARRAY_PREFIX = "[L";@b@    /**@b@     * Map with primitive type name as key and corresponding primitive type as@b@     * value, for example: "int" -> "int.class".@b@     */@b@    private static final Map<String, Class<?>> primitiveTypeNameMap = new HashMap<String, Class<?>>(16);@b@    /**@b@     * Map with primitive wrapper type as key and corresponding primitive type@b@     * as value, for example: Integer.class -> int.class.@b@     */@b@    private static final Map<Class<?>, Class<?>> primitiveWrapperTypeMap = new HashMap<Class<?>, Class<?>>(8);@b@@b@    static {@b@        primitiveWrapperTypeMap.put(Boolean.class, boolean.class);@b@        primitiveWrapperTypeMap.put(Byte.class, byte.class);@b@        primitiveWrapperTypeMap.put(Character.class, char.class);@b@        primitiveWrapperTypeMap.put(Double.class, double.class);@b@        primitiveWrapperTypeMap.put(Float.class, float.class);@b@        primitiveWrapperTypeMap.put(Integer.class, int.class);@b@        primitiveWrapperTypeMap.put(Long.class, long.class);@b@        primitiveWrapperTypeMap.put(Short.class, short.class);@b@@b@        Set<Class<?>> primitiveTypeNames = new HashSet<Class<?>>(16);@b@        primitiveTypeNames.addAll(primitiveWrapperTypeMap.values());@b@        primitiveTypeNames.addAll(Arrays@b@                .asList(new Class<?>[]{boolean[].class, byte[].class, char[].class, double[].class,@b@                        float[].class, int[].class, long[].class, short[].class}));@b@        for (Iterator<Class<?>> it = primitiveTypeNames.iterator(); it.hasNext(); ) {@b@            Class<?> primitiveClass = (Class<?>) it.next();@b@            primitiveTypeNameMap.put(primitiveClass.getName(), primitiveClass);@b@        }@b@    }@b@@b@    public static Class<?> forNameWithThreadContextClassLoader(String name)@b@            throws ClassNotFoundException {@b@        return forName(name, Thread.currentThread().getContextClassLoader());@b@    }@b@@b@    public static Class<?> forNameWithCallerClassLoader(String name, Class<?> caller)@b@            throws ClassNotFoundException {@b@        return forName(name, caller.getClassLoader());@b@    }@b@@b@    public static ClassLoader getCallerClassLoader(Class<?> caller) {@b@        return caller.getClassLoader();@b@    }@b@@b@    /**@b@     * get class loader@b@     *@b@     * @param cls@b@     * @return class loader@b@     */@b@    public static ClassLoader getClassLoader(Class<?> cls) {@b@        ClassLoader cl = null;@b@        try {@b@            cl = Thread.currentThread().getContextClassLoader();@b@        } catch (Throwable ex) {@b@            // Cannot access thread context ClassLoader - falling back to system class loader...@b@        }@b@        if (cl == null) {@b@            // No thread context class loader -> use class loader of this class.@b@            cl = cls.getClassLoader();@b@        }@b@        return cl;@b@    }@b@@b@    /**@b@     * Return the default ClassLoader to use: typically the thread context@b@     * ClassLoader, if available; the ClassLoader that loaded the ClassUtils@b@     * class will be used as fallback.@b@     * <p>@b@     * Call this method if you intend to use the thread context ClassLoader in a@b@     * scenario where you absolutely need a non-null ClassLoader reference: for@b@     * example, for class path resource loading (but not necessarily for@b@     * <code>Class.forName</code>, which accepts a <code>null</code> ClassLoader@b@     * reference as well).@b@     *@b@     * @return the default ClassLoader (never <code>null</code>)@b@     * @see java.lang.Thread#getContextClassLoader()@b@     */@b@    public static ClassLoader getClassLoader() {@b@        return getClassLoader(ClassHelper.class);@b@    }@b@@b@    /**@b@     * Same as <code>Class.forName()</code>, except that it works for primitive@b@     * types.@b@     */@b@    public static Class<?> forName(String name) throws ClassNotFoundException {@b@        return forName(name, getClassLoader());@b@    }@b@@b@    /**@b@     * Replacement for <code>Class.forName()</code> that also returns Class@b@     * instances for primitives (like "int") and array class names (like@b@     * "String[]").@b@     *@b@     * @param name        the name of the Class@b@     * @param classLoader the class loader to use (may be <code>null</code>,@b@     *                    which indicates the default class loader)@b@     * @return Class instance for the supplied name@b@     * @throws ClassNotFoundException if the class was not found@b@     * @throws LinkageError           if the class file could not be loaded@b@     * @see Class#forName(String, boolean, ClassLoader)@b@     */@b@    public static Class<?> forName(String name, ClassLoader classLoader)@b@            throws ClassNotFoundException, LinkageError {@b@@b@        Class<?> clazz = resolvePrimitiveClassName(name);@b@        if (clazz != null) {@b@            return clazz;@b@        }@b@@b@        // "java.lang.String[]" style arrays@b@        if (name.endsWith(ARRAY_SUFFIX)) {@b@            String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length());@b@            Class<?> elementClass = forName(elementClassName, classLoader);@b@            return Array.newInstance(elementClass, 0).getClass();@b@        }@b@@b@        // "[Ljava.lang.String;" style arrays@b@        int internalArrayMarker = name.indexOf(INTERNAL_ARRAY_PREFIX);@b@        if (internalArrayMarker != -1 && name.endsWith(";")) {@b@            String elementClassName = null;@b@            if (internalArrayMarker == 0) {@b@                elementClassName = name@b@                        .substring(INTERNAL_ARRAY_PREFIX.length(), name.length() - 1);@b@            } else if (name.startsWith("[")) {@b@                elementClassName = name.substring(1);@b@            }@b@            Class<?> elementClass = forName(elementClassName, classLoader);@b@            return Array.newInstance(elementClass, 0).getClass();@b@        }@b@@b@        ClassLoader classLoaderToUse = classLoader;@b@        if (classLoaderToUse == null) {@b@            classLoaderToUse = getClassLoader();@b@        }@b@        return classLoaderToUse.loadClass(name);@b@    }@b@@b@    /**@b@     * Resolve the given class name as primitive class, if appropriate,@b@     * according to the JVM's naming rules for primitive classes.@b@     * <p>@b@     * Also supports the JVM's internal class names for primitive arrays. Does@b@     * <i>not</i> support the "[]" suffix notation for primitive arrays; this is@b@     * only supported by {@link #forName}.@b@     *@b@     * @param name the name of the potentially primitive class@b@     * @return the primitive class, or <code>null</code> if the name does not@b@     * denote a primitive class or primitive array class@b@     */@b@    public static Class<?> resolvePrimitiveClassName(String name) {@b@        Class<?> result = null;@b@        // Most class names will be quite long, considering that they@b@        // SHOULD sit in a package, so a length check is worthwhile.@b@        if (name != null && name.length() <= 8) {@b@            // Could be a primitive - likely.@b@            result = (Class<?>) primitiveTypeNameMap.get(name);@b@        }@b@        return result;@b@    }@b@@b@    public static String toShortString(Object obj) {@b@        if (obj == null) {@b@            return "null";@b@        }@b@        return obj.getClass().getSimpleName() + "@" + System.identityHashCode(obj);@b@@b@    }@b@}