ClassUtils
CGLIB_CLASS_SEPARATOR = "$$";
#public static ClassLoader getDefaultClassLoader() 获取默认ClassLoader,获取结果通常是AppClassLoader。优先级:Thread.currentThread().getContextClassLoader(); -> ClassUtils.class.getClassLoader(); -> ClassLoader.getSystemClassLoader();
#public static ClassLoader overrideThreadContextClassLoader(@Nullable ClassLoader classLoaderToUse) 覆盖当前线程的ClassLoader,并返回覆盖前的ClassLoader,若无需覆盖(classLoaderToUse是null或新旧eq)则返回null
#public static Class> forName(String name, @Nullable ClassLoader classLoader) Class.forName的加强,允许name是java基本类型如int -> int.class,允许name的入参是数组形式,例如org.springframework.tests.sample.objects.TestObject[] -> TestObject[].class
##使用resolvePrimitiveClassName获取基本类型class,是null再从缓存中获取,若命中则返回
##若name以[]结尾(说明是数组形式),则截取到[]之前部分,再递归使用forName取得class,使用Array.newInstance(elementClass, 0).getClass();响应数组[]形式的class
##若name以 [L 开头以 ; 结尾(说明是数组形式),如[Ljava.lang.String; ,则截取[L和;之间部分,再递归使用forName取得class,使用Array.newInstance(elementClass, 0).getClass();响应数组[]形式的class
##若name以[开头(针对[[I 或 [[Ljava.lang.String; 形式的二维数组),则截取[之后部分,再递归使用forName处理
##若以上都不符,则使用Class.forName(name, false, clToUse); ,若catch到ClassNotFoundException,尝试将最后的.号换成$后再一次Class.forName(name, false, clToUse); (为了应对可能是.号方式的内部类 如org.springframework.util.ClassUtilsTests.NestedClass),若还是没有则把ClassNotFoundException抛出
#public static Class> resolveClassName(String className, @Nullable ClassLoader classLoader) 委托使用forName并将异常包装为IllegalArgumentException
#public static boolean isPresent(String className, @Nullable ClassLoader classLoader) 委托使用forName检查类是否存在
#public static boolean isVisible(Class> clazz, @Nullable ClassLoader classLoader) 检查类对给定的ClassLoader是否可见。若classLoader是null->true;若clazz.getClassLoader() == classLoader -> true;最后使用isLoadable
#public static boolean isCacheSafe(Class> clazz, @Nullable ClassLoader classLoader) 检查clazz是由给定的类加载器加载还是由它的父类加载。参数classLoader可能为null,此时表示BootstrapClassLoader
##若clazz.getClassLoader() == classLoader 或 clazz.getClassLoader()是null(是null则说明该clazz是由BootstrapClassLoader加载的,如rt.jar下的String.class,BootstrapClassLoader是其他类加载器的父加载器) -> true
##若classLoader ==null -> false
##若clazz是由classLoader 加载或classLoader的parent加载的 -> true ; 否则false
#public static Class> resolvePrimitiveClassName(@Nullable String name) 根据name参数返回原始类型(基本类型),若name不属于基本类型则返回null
boolean -> boolean.class
byte -> byte.class
char->char.class
double -> double.class
float->float.class
int->int.class
long->long.class
short->short.class
void->void.class
{void=void, double=double, byte=byte, [B=class [B, [C=class [C, [D=class [D, [F=class [F, float=float, int=int, long=long, [I=class [I, [J=class [J, boolean=boolean, [S=class [S, char=char, short=short, [Z=class [Z}
#private static boolean isLoadable(Class> clazz, ClassLoader classLoader) 若clazz == classLoader.loadClass(clazz.getName()) -> true(说明classLoader可以加载该clazz并且加载后的class是同一个,因为JVM规范同一个classLoader加载同一个类,只会存在一个class);否则false
#public static boolean isPrimitiveWrapper(Class> clazz) 检查clazz是否包装类型 Boolean.class, Character.class, Byte.class, Short.class,Integer.class, Long.class, Float.class, Double.class, Void.class
#public static boolean isPrimitiveOrWrapper(Class> clazz) 检查clazz是否基本类型或包装类型 boolean, byte,char, short, int, long, float, double, void 以及 Boolean, Byte, Character, Short, Integer, Long, Float, Double, Void
#public static boolean isPrimitiveArray(Class> clazz) 检查clazz是否基本类型的数组
#public static boolean isPrimitiveWrapperArray(Class> clazz) 检查clazz是否包装类型的数组
#public static Class> resolvePrimitiveIfNecessary(Class> clazz) 获取类型的包装类型 int.class -> Integer.class, Integer.class -> Integer.class, 自定义.class -> 自定义.class
#public static boolean isAssignable(Class> lhsType, Class> rhsType) 检查左边是否对右边isAssignable。若lhsType.isAssignableFrom(rhsType) -> true;若左边是基本类型,则获取右边的基本类型进行==匹配;#否则获取右边的包装类型执行isAssignableFrom
#public static boolean isAssignablevalue(Class> type, @Nullable Object value) 检查type是否isAssignable value的类型
#public static String convertResourcePathToClassName(String resourcePath) 把resourcePath中的路径分割符/ 替换成 包分隔符.
#public static String convertClassNameToResourcePath(String className) 把className中的包分隔符. 替换成 路径分割符/
#public static String addResourcePathToPackagePath(Class> clazz, String resourceName) 给resourceName追加clazz的package名作为前缀。例如clazz=java.lang.reflect.Proxy resourceName=xyzabc.xml -> java/lang/reflect/xyzabc.xml
#public static String classPackageAsResourcePath(@Nullable Class> clazz) 获取clazz的package名并以 / 分割
#public static String classNamesToString(Class>... classes) 对classes以数组方式toString,如ArrayList.class,Integer.class -> [java.util.ArrayList, java.lang.Integer]
#public static String classNamesToString(@Nullable Collection
#public static Class>[] toClassArray(@Nullable Collection
#public static Class>[] getAllInterfaces(Object instance) 最终使用getAllInterfacesForClassAsSet获取所有接口
#public static Class>[] getAllInterfacesForClass(Class> clazz) 最终使用getAllInterfacesForClassAsSet获取所有接口
#public static Class>[] getAllInterfacesForClass(Class> clazz, @Nullable ClassLoader classLoader) 最终使用getAllInterfacesForClassAsSet获取所有接口
#public static Set
#public static Set
#public static Set
#public static Class> createCompositeInterface(Class>[] interfaces, @Nullable ClassLoader classLoader) 把interfaces组合起来产生一个新的代理接口,在JDK9过时
#public static Class> determineCommonAncestor(@Nullable Class> clazz1, @Nullable Class> clazz2) 获取2个类的共同父类。例如 Integer和 Float ->Number,Runnable和List -> null
#public static boolean isJavaLanguageInterface(Class> ifc) 是否java语言的接口:Serializable.class, Externalizable.class,Closeable.class, AutoCloseable.class, Cloneable.class, Comparable.class
#public static boolean isInnerClass(Class> clazz) 检查是否是内部类,要求不是static class
#public static Class> getUserClass(Object instance) 委托getUserClass
#public static Class> getUserClass(Class> clazz) 若clazz含$$(CGLIB),则若其 superclass != null && superclass != Object.class 即return superclass;否则return clazz;
#public static String getDescriptiveType(@Nullable Object value) 获取实例对应的类描述。若value==null ,return null; 若value的class是代理类 -> clazz.getName() + "implementing"+","实现了哪些接口的名称(,号间隔)



