克隆 - 支持泛型的克隆接口和克隆类
泛型克隆接口
泛型克隆接口:cn.hutool.core.clone,定义了一个返回泛型的成员方法,这样,实现此接口后会提示必须实现一个public的clone方法,调用父类clone方法即可;
private static class Cat implements Cloneable<Cat>{
private String name = "miaomiao";
private int age = 2;
@Override
public Cat clone() {
try {
return (Cat) super.clone();
} catch (CloneNotSupportedException e) {
throw new CloneRuntimeException(e);
}
}
}
泛型克隆类
泛型克隆类:cn.hutool.clone.CloneSupport
实现克隆接口,依旧有不方便之处,就是必须自己实现一个public类型的clone()方法,还要调用父类(Object)的clone方法并处理异常。
private static class Dog extends CloneSupport<Dog>{
private String name = "wangwang";
private int age = 3;
}
使用CloneSupport的前提是没有继承任何的类,Java不支持多重继承(可以让父类继承这个类,如果可以)。如果没办法继承类,那只有实现cn.hutool.clone.Cloneable,因此hutool提供了这两种方式,任选其一,在便捷和灵活上都提供了支持。
深克隆
实现Cloneable接口后克隆的对象是浅克隆,要想实现深克隆需要使用:
ObjectUtil.cloneByStream(obj)
对象必须实现Serializable接口。
ObjectUtil同样提供一些静态方法:clone(obj)、cloneIfPossible(obj)用于简化克隆调用
工具类
对象工具 - ObjectUtil
在我们的日常使用中,有些方法是针对Object通用的,这些方法不区分何种对象,针对这些方法,Hutool封装为ObjectUtil
- ObjectUtil.equal - 比较两个对象是否相等,相等需满足以下条件之一
- obj1 == null && obj2 == null
- obj1.equals(obj2)
- ObjectUtil.length - 计算对象长度,如果是字符串调用其length方法,集合类调用其size方法,数组调用其length属性,其他可遍历对象遍历计算长度。
支持的类型包括:CharSequence、Collection、Map、Iterator、Enumeration、Array
- ObjectUtil.contains - 对象中是否包含元素。
支持:String、Collection、Map、Iterator、Enumeration、Array
- 判断是否为null
ObjectUtil.isNull ObjectUtil.isNotNull
- 克隆
ObjectUtil.clone 克隆对象,如果对象实现Cloneable接口,调用其clone方法,如果实现Serializable接口,执行深度克隆,否则返回null。 ObjectUtil.cloneIfPossible 返回克隆后的对象,如果克隆失败,返回原对象 ObjectUtil.cloneByStream 序列化后拷贝流的方式克隆,对象必须实现Serializable接口
- 序列化和反序列化
serialize 序列化,调用JDK序列化 unserialize 反序列化,调用JDK
- 判断基本类型
ObjectUtil.isBasicType 判断是否为基本类型,包括包装类型和非包装类型。
身份证工具 - IdcardUtil
身份证的验证主要是正则方式(位数,数字范围等),但是中国身份证,尤其18位身份证每一位都有严格规定,并且最后一位为校验位。而我们在实际应用中,针对身份证的验证理应严格至此。于是IdcardUtil应运而生。
IdcardUtil现在支持大陆15位、18位身份证,港澳台10位身份证。
工具中主要的方法包括:
- isValidCard 验证身份证是否合法
- convert15To18 身份证15位转18位
- getBirthByIdCard 获取生日
- getAgeByIdCard 获取年龄
- getYearByIdCard 获取生日年
- getMonthByIdCard 获取生日月
- getDayByIdCard 获取生日天
- getGenderByIdCard 获取性别
- getProvinceByIdCard 获取省份
社会信用代码工具 - CreditCodeUtil
法人和其他组织统一社会信用代码制度,相当于让法人和其他组织拥有了一个全国统一的“身份证号”。
- 第一部分:登记管理部门代码1位 (数字或大写英文字母)
- 第二部分:机构类别代码1位 (数字或大写英文字母)
- 第三部分:登记管理机关行政区划码6位 (数字)
- 第四部分:主体标识码(组织机构代码)9位 (数字或大写英文字母)
- 第五部分:校验码1位 (数字或大写英文字母)
此工具主要提供校验和随机生成。
校验:
String testCreditCode = "91310110666007217T";
CreditCodeUtil.isCreditCode(testCreditCode);
随机社会信用代码:
final String s = CreditCodeUtil.randomCreditCode();
语言特性
断言-Assert
Java中有assert关键字,但是存在许多问题:
- assert关键字需要在运行时候显式开启才能生效,否则你的断言就没有任何意义。
- 用assert代替if是陷阱之二。assert的判断和if语句差不多,但两者的作用有着本质的区别:assert关键字本意上是为测试调试程序时使用的,但如果不小心用assert来控制了程序的业务流程,那在测试调试结束后去掉assert关键字就意味着修改了程序的正常的逻辑。
- assert断言失败将面临程序的退出。
因此,并不建议使用此关键字。相应的,在Hutool中封装了更加友好的Assert类,用于断言判定。
Assert类更像是Junit中的Assert类,也很像Guava中的Preconditions,主要作用是在方法或者任何地方对参数的有效性做校验。当不满足断言条件时,会抛出IllegalArgumentException或IllegalStateException异常。
String a = null;
cn.hutool.lang.Assert.isNull(a);
更多方法:
- isTrue 是否True
- isNull 是否是null值,不为null抛出异常
- notNull 是否非null值
- notEmpty 是否非空
- notBlank 是否非空白符
- notContain 是否为子串
- notEmpty 是否非空
- noNullElements 数组中是否包含null元素
- isInstanceOf 是否类实例
- isAssignable 是子类和父类关系
- state 会抛出IllegalStateException异常
JavaBean
DynaBean:通过Java反射机制操作JavaBean,以达到动态语言的某些特性
Bean工具-BeanUtil
把一个拥有对属性进行set和get方法的类,我们就可以称之为JavaBean。
实际上JavaBean就是一个Java类,在这个Java类中就默认形成了一种规则——对属性进行设置和获得。而反之将说Java类就是一个JavaBean,这种说法是错误的,因为一个java类中不一定有对属性的设置和获得的方法(也就是不一定有set和get方法)。
Bean工具类主要是针对这些setXXX和getXXX方法进行操作,比如将Bean对象转为Map等等。
BeanUtil.isBean 方法根据是否存在只有一个参数的setXXX方法或者public类型的字段来判定是否是一个Bean对象。这样的判定方法主要目的是保证至少有一个setXXX方法用于属性注入。
boolean isBean = BeanUtil.isBean(HashMap.class);
- 内省 Introspector
把一类中需要进行设置和获得的属性访问权限设置为private(私有的)让外部的使用者看不见摸不着,而通过public(共有的)set和get方法来对其属性的值来进行设置和获得,而内部的操作具体是怎样的?外界使用的人不用知道,这就称为内省。
BeanUtil.getPropertyDescriptors 获得Bean字段描述数组
PropertyDescriptor[] propertyDescriptors = BeanUtil.getPropertyDescriptors(SubPerson.class);
BeanUtil.getFieldNamePropertyDescriptorMap 获得字段名和字段描述Map
BeanUtil.getPropertyDescriptor 获得Bean类指定属性描述
更多用法参考官方文档
空检查属性获取-OptinalBean
在嵌套对象的属性获取中,由于子对象无法得知是否为null,每次获取属性都要检查属性兑现是否为null,使得代码会变得特备臃肿,因此使用OptionalBean来优雅的链式获取属性对象值。
定义一个嵌套的bean
@Data
public static class User {
private String name;
private String gender;
private School school;
@Data
public static class School {
private String name;
private String address;
}
}
获取address属性:
User user = new User();
user.setName("hello");
String addressValue = OptionalBean.ofNullable(user)
.getBean(User::getSchool)
.getBean(User.School::getAddress).get();
由于school对象的值为null,一般直接获取会报空指针,使用OptionalBean即可避免判断。
|