我们项目大多数都是基于Spring架构,Spring自身包含了许多实用的工具类,学习这些工具类的使用不仅能让我们达到事半功倍的效果,而且还能减少不必要的额外的工具类的引入。查看这些工具类的源码时发现它们都是abstract类型的,这是因为工具类的方法一般都是static静态方法,静态方法和类绑定,类加载后就能使用了,无需实例化(刚好abstract类不能直接实例化,并且可以定义非抽象方法),所以工具类定义为abstract类型再合适不过。
1 | private static void print(Object value) { |
ClassUtils
org.springframework.util.classUtils包含一些和java.lang.Class相关的实用方法。
getDefaultClassLoader
ClassLoader getDefaultClassLoader()
获取当前线程上下文的类加载器:
1 | print(ClassUtils.getDefaultClassLoader()); |
1 | sun.misc.Launcher$AppClassLoader@18b4aac2 |
overrideThreadContextClassLoader
ClassLoader overrideThreadContextClassLoader(@Nullable ClassLoader classLoaderToUse)
用特定的类加载器覆盖当前线程上下文的类加载器:
1 | print(ClassUtils.getDefaultClassLoader()); |
1 | sun.misc.Launcher$AppClassLoader@18b4aac2 |
forName
forName(String name, @Nullable ClassLoader classLoader)
通过类名返回类实例,类似于Class.forName(),但功能更强,可以用于原始类型,内部类等:
1 | ClassLoader classLoader = ClassUtils.getDefaultClassLoader(); |
1 | int |
isPresent
boolean isPresent(String className, @Nullable ClassLoader classLoader)
判断当前classLoader是否包含目标类型(包括它的所有父类和接口):
1 | ClassLoader classLoader = ClassUtils.getDefaultClassLoader(); |
1 | true |
resolvePrimitiveClassName
Class<?> resolvePrimitiveClassName(@Nullable String name)
通过给定类名获取原始类:
1 | print(ClassUtils.resolvePrimitiveClassName("int")); |
1 | int |
isPrimitiveWrapper
boolean isPrimitiveWrapper(Class<?> clazz)
判断给定类是否为包装类,如Boolean, Byte, Character, Short, Integer, Long, Float, Double 或者 Void:
1 | print(ClassUtils.isPrimitiveWrapper(Integer.class)); |
1 | true |
类似的方法还有isPrimitiveOrWrapper
判断是否为原始类或者包装类、isPrimitiveWrapperArray
判断是否为包装类数组、isPrimitiveArray
判断是否为原始类数组。
resolvePrimitiveIfNecessary
Class<?> resolvePrimitiveIfNecessary(Class<?> clazz)
如果给定类是原始类,则返回对应包装类,否则直接返回给定类:
1 | print(ClassUtils.resolvePrimitiveIfNecessary(int.class)); |
1 | class java.lang.Integer |
isAssignable
boolean isAssignable(Class<?> lhsType, Class<?> rhsType)
通过反射检查,是否可以将rhsType赋值给lhsType(注意,包装类型可以赋值给相应的原始类型,自动拆装箱机制):
1 | print(ClassUtils.isAssignable(Integer.class, int.class)); |
1 | true |
isAssignableValue
boolean isAssignableValue(Class<?> type, @Nullable Object value)
判断给定的值是否符合给定的类型:
1 | print(ClassUtils.isAssignableValue(Integer.class, 1)); |
1 | true |
convertResourcePathToClassName
String convertResourcePathToClassName(String resourcePath)
将类路径转换为全限定类名:
1 | print(ClassUtils.convertResourcePathToClassName("java/lang/String")); |
1 | java.lang.String |
实际上就是将/
替换为.
。convertClassNameToResourcePath
方法功能相反。
classNamesToString
String classNamesToString(Class<?>... classes)
直接看演示不解释:
1 | print(ClassUtils.classNamesToString(String.class, Integer.class, BeanPostProcessor.class)); |
1 | [java.lang.String, java.lang.Integer, org.springframework.beans.factory.config.BeanPostProcessor] |
getAllInterfaces
Class<?>[] getAllInterfaces(Object instance)
返回给定实例对象所实现接口类型集合:
1 | AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor(); |
1 | interface org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor |
类似的方法还有getAllInterfacesForClass
、getAllInterfacesAsSet
、getAllInterfacesForClassAsSet
determineCommonAncestor
Class<?> determineCommonAncestor(@Nullable Class<?> clazz1, @Nullable Class<?> clazz2)
寻找给定类型的共同祖先(所谓共同祖先指的是给定类型调用class.getSuperclass
获得的共同类型,如果给定类型是Object.class,接口,原始类型或者Void,直接返回null):
1 | // 它两都是接口 |
1 | null |
isInnerClass
boolean isInnerClass(Class<?> clazz)
判断给定类型是否为内部类(非静态):
1 | class A { |
1 | static class A { |
1 | static class A { |
isCglibProxy
boolean isCglibProxy(Object object)
是否为Cglib代理对象:
1 |
|
1 | true |
配置类不由Cglib代理的话,返回为false:
1 |
|
1 | false |
不过这个方法废弃了,建议使用org.springframework.aop.support.AopUtils.isCglibProxy(Object)
方法。
getUserClass
Class<?> getUserClass(Object instance)
返回给定实例对应的类型,如果实例是Cglib代理后的对象,则返回代理的目标对象类型:
1 | print(ClassUtils.getUserClass("Hello")); // class java.lang.String |
Cglib代理例子:
1 |
|
1 | class cc.mrbird.aop.AopApplication$MyConfigure$$EnhancerBySpringCGLIB$$e51ce45 |
matchesTypeName
boolean matchesTypeName(Class<?> clazz, @Nullable String typeName)
判断给定class和类型名称是否匹配:
1 | print(ClassUtils.matchesTypeName(String.class, "java.lang.String")); // true |
getShortName
String getShortName(Class<?> clazz)
返回类名:
1 | print(ClassUtils.getShortName(String.class)); // String |
getShortNameAsProperty
String getShortNameAsProperty(Class<?> clazz)
返回首字母小写的类名,如果是内部类的话,则去掉外部类名:
1 | print(ClassUtils.getShortNameAsProperty(String.class)); // string |
1 | class A { |
getClassFileName
String getClassFileName(Class<?> clazz)
返回类名+.class:
1 | print(ClassUtils.getShortNameAsProperty(String.class)); // String.class |
getPackageName
String getPackageName(Class<?> clazz)
返回包名:
1 | print(ClassUtils.getShortNameAsProperty(String.class)); // java.lang |
getQualifiedName
String getQualifiedName(Class<?> clazz)
返回全限定类名,如果是数组类型则末尾加[]:
1 | print(ClassUtils.getQualifiedName(String.class)); |
1 | java.lang.String |
getQualifiedMethodName
String getQualifiedMethodName(Method method)
获取方法的全限定名:
1 | print(ClassUtils.getQualifiedMethodName( |
1 | org.springframework.util.ClassUtils.getQualifiedMethodName |
hasConstructor
boolean hasConstructor(Class<?> clazz, Class<?>... paramTypes)
判断给定类型是否有给定类型参数构造器:
1 | print(ClassUtils.hasConstructor(String.class, String.class)); |
1 | true |
getConstructorIfAvailable
<T> Constructor<T> getConstructorIfAvailable(Class<T> clazz, Class<?>... paramTypes)
返回给定类型的给定参数类型构造器,没有的话返回null:
1 | Constructor<String> constructorIfAvailable = ClassUtils.getConstructorIfAvailable(String.class, String.class); |
1 | true |
hasMethod
boolean hasMethod(Class<?> clazz, Method method)
判断给定类型是否有指定的方法:
1 | Method hasMethod = ClassUtils.class.getDeclaredMethod("hasMethod", Class.class, Method.class); |
重载方法boolean hasMethod(Class<?> clazz, String methodName, Class<?>... paramTypes)
。
getMethod
Method getMethod(Class<?> clazz, String methodName, @Nullable Class<?>... paramTypes)
从指定类型中找指定方法,没找到抛IllegalStateException异常:
1 | ClassUtils.getMethod(ClassUtils.class,"hello", String.class); |
1 | java.lang.IllegalStateException: Expected method not found: java.lang.NoSuchMethodException: org.springframework.util.ClassUtils.hello(java.lang.String) |
如果希望没找到返回null,而非抛异常,可以用getMethodIfAvailable
方法。
getMethodCountForName
int getMethodCountForName(Class<?> clazz, String methodName)
从指定类型中通过方法名称查找该方法个数(重写、重载、非public的都算):
1 | print(ClassUtils.getMethodCountForName(ClassUtils.class,"hasMethod")); // 2 |
类似的方法还有hasAtLeastOneMethodWithName
,至少得有一个。
getStaticMethod
Method getStaticMethod(Class<?> clazz, String methodName, Class<?>... args)
获取给定类型的静态方法,如果该方法不是静态的或者没有这个方法,则返回null:
1 | Method method = ClassUtils.getStaticMethod(ClassUtils.class, "getDefaultClassLoader"); |
1 | true |
FileSystemUtils
文件系统实用工具类
deleteRecursively
boolean deleteRecursively(@Nullable File root)
递归删除指定文件或目录,删除成功返回true,失败返回false,不会抛出异常。
新建一个多层级目录:
实用File的delete目录尝试删除a目录:
1 | File file = new File("a"); |
因为a目录包含子目录(文件),所以应该使用递归删除:
1 | File file = new File("a"); |
重载方法boolean deleteRecursively(@Nullable Path root)
和该方法功能相似,但该方法可能会抛出IO异常。
copyRecursively
void copyRecursively(File src, File dest)
递归复制src文件到dest(目标路径不存在则自动创建):
新建一个多层级目录:
1 | File src = new File("a"); |
重载方法void copyRecursively(Path src, Path dest)
。
StreamUtils
包含一些文件流的实用方法默认的缓冲区大小为4096bytes。
未完待续,慢慢记录😴