一、前言
关于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@}