ObjUtil
ObjUtil是Hutool中用于处理对象的工具类,提供了丰富的对象操作方法,包括判空、比较、克隆、序列化等功能,是Java开发中常用的工具类之一。
# 功能介绍
- 对象比较:支持多种类型对象的相等性比较,包括数字、数组、BigDecimal等
- 对象长度计算:支持字符串、集合、数组、迭代器等多种类型的长度计算
- 包含关系判断:判断对象是否包含指定元素
- 空值处理:提供全面的空值判断和默认值处理方法
- 对象克隆:支持浅克隆、深克隆和序列化克隆
- 类型判断:判断对象是否为基本类型、有效数字等
- 泛型处理:获取对象的泛型参数类型
# 核心方法
# 1. 对象比较
# equals
比较两个对象是否相等,支持数字、数组等特殊类型的比较。
// 基本类型比较
boolean eq1 = ObjUtil.equals(1, 1);
// 结果:true
// 数字类型比较
boolean eq2 = ObjUtil.equals(1L, 1);
// 结果:true
// BigDecimal比较
boolean eq3 = ObjUtil.equals(new BigDecimal("1.0"), new BigDecimal("1"));
// 结果:true
// 数组比较
boolean eq4 = ObjUtil.equals(new int[]{1, 2}, new int[]{1, 2});
// 结果:true
# notEquals
比较两个对象是否不相等,是equals方法的取反。
boolean ne1 = ObjUtil.notEquals(1, 2);
// 结果:true
boolean ne2 = ObjUtil.notEquals(1, 1);
// 结果:false
# 2. 对象长度计算
# length
计算对象的长度,支持多种类型。
// 字符串长度
int len1 = ObjUtil.length("Hello");
// 结果:5
// 集合长度
int len2 = ObjUtil.length(Arrays.asList(1, 2, 3));
// 结果:3
// 数组长度
int len3 = ObjUtil.length(new int[]{1, 2, 3, 4});
// 结果:4
// Map长度
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
int len4 = ObjUtil.length(map);
// 结果:2
// 迭代器长度
int len5 = ObjUtil.length(Arrays.asList(1, 2, 3).iterator());
// 结果:3
# 3. 包含关系判断
# contains
判断对象是否包含指定元素。
// 字符串包含
boolean contains1 = ObjUtil.contains("Hello", "ell");
// 结果:true
// 集合包含
boolean contains2 = ObjUtil.contains(Arrays.asList(1, 2, 3), 2);
// 结果:true
// 数组包含
boolean contains3 = ObjUtil.contains(new int[]{1, 2, 3}, 2);
// 结果:true
// Map包含值
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
boolean contains4 = ObjUtil.contains(map, 1);
// 结果:true
# 4. 空值处理
# isNull / isNotNull
检查对象是否为null。
boolean null1 = ObjUtil.isNull(null);
// 结果:true
boolean null2 = ObjUtil.isNull("test");
// 结果:false
boolean notNull1 = ObjUtil.isNotNull("test");
// 结果:true
# isEmpty / isNotEmpty
判断对象是否为空,支持多种类型。
// 字符串为空
boolean empty1 = ObjUtil.isEmpty("");
// 结果:true
// 集合为空
boolean empty2 = ObjUtil.isEmpty(new ArrayList<>());
// 结果:true
// 数组为空
boolean empty3 = ObjUtil.isEmpty(new int[]{});
// 结果:true
// Map为空
boolean empty4 = ObjUtil.isEmpty(new HashMap<>());
// 结果:true
// 非空对象
boolean notEmpty1 = ObjUtil.isNotEmpty("test");
// 结果:true
# 5. 默认值处理
# defaultIfNull
如果对象为null,返回默认值。
String str1 = ObjUtil.defaultIfNull(null, "default");
// 结果:"default"
String str2 = ObjUtil.defaultIfNull("value", "default");
// 结果:"value"
# defaultIfNull(Supplier)
如果对象为null,返回Supplier提供的默认值。
String str1 = ObjUtil.defaultIfNull(null, () -> "lazy-default");
// 结果:"lazy-default"
// 当对象不为null时,Supplier不会被调用
String str2 = ObjUtil.defaultIfNull("value", () -> {
Console.log("This won't be printed");
return "default";
});
// 结果:"value"
# defaultIfNull(Function, R)
如果对象不为null,返回handler处理后的结果,否则返回默认值。
String str1 = ObjUtil.defaultIfNull("hello", String::toUpperCase, "default");
// 结果:"HELLO"
String str2 = ObjUtil.defaultIfNull(null, String::toUpperCase, "default");
// 结果:"default"
# apply
如果对象不为null,返回handler处理后的结果,否则返回null。
String str1 = ObjUtil.apply("hello", String::toUpperCase);
// 结果:"HELLO"
String str2 = ObjUtil.apply(null, String::toUpperCase);
// 结果:null
# accept
如果对象不为null,执行Consumer处理,否则不执行。
ObjUtil.accept("hello", s -> Console.log(s.toUpperCase()));
// 输出:HELLO
ObjUtil.accept(null, s -> Console.log(s.toUpperCase()));
// 无输出
# 6. 对象克隆
# clone
克隆对象,支持多种克隆方式。
// 克隆数组
int[] arr1 = {1, 2, 3};
int[] arr2 = (int[]) ObjUtil.clone(arr1);
// 结果:arr2 = [1, 2, 3],与arr1不同引用
// 克隆实现Cloneable接口的对象
Person p1 = new Person("张三", 20);
Person p2 = ObjUtil.clone(p1);
// 结果:p2是p1的克隆对象
// 克隆实现Serializable接口的对象
Person p3 = ObjUtil.clone(p1);
// 结果:p3是p1的深克隆对象
# cloneIfPossible
尝试克隆对象,如果克隆失败,返回原对象。
// 可克隆对象
Person p1 = new Person("张三", 20);
Person p2 = ObjUtil.cloneIfPossible(p1);
// 结果:p2是p1的克隆对象
// 不可克隆对象
String str1 = "test";
String str2 = ObjUtil.cloneIfPossible(str1);
// 结果:str2与str1是同一个对象(String是不可变的)
# cloneByStream
通过序列化后拷贝流的方式克隆对象。
// 实现Serializable接口的对象
Person p1 = new Person("张三", 20);
Person p2 = ObjUtil.cloneByStream(p1);
// 结果:p2是p1的深克隆对象
# 7. 类型判断
# isBasicType
判断对象是否为基本类型,包括包装类型和原始类型。
boolean basic1 = ObjUtil.isBasicType(1);
// 结果:true
boolean basic2 = ObjUtil.isBasicType("test");
// 结果:true
boolean basic3 = ObjUtil.isBasicType(new Person());
// 结果:false
# isValidIfNumber
判断对象是否为有效的数字,主要用于检查浮点数是否为有意义的数值。
boolean valid1 = ObjUtil.isValidIfNumber(1);
// 结果:true
boolean valid2 = ObjUtil.isValidIfNumber(Double.NaN);
// 结果:false
boolean valid3 = ObjUtil.isValidIfNumber(Double.POSITIVE_INFINITY);
// 结果:false
boolean valid4 = ObjUtil.isValidIfNumber("test");
// 结果:true(非数字类型返回true)
# 8. 泛型处理
# getTypeArgument
获得给定类的第一个泛型参数。
// 假设List<String> list = new ArrayList<>();
Class<?> type1 = ObjUtil.getTypeArgument(list);
// 结果:String.class
// 获得指定下标的泛型参数
// 假设Map<String, Integer> map = new HashMap<>();
Class<?> type2 = ObjUtil.getTypeArgument(map, 1);
// 结果:Integer.class
# 应用场景
# 1. 避免空指针异常
在Java开发中,空指针异常是最常见的异常之一。使用ObjUtil可以有效地避免空指针异常:
// 安全比较两个对象
if (ObjUtil.equals(obj1, obj2)) {
// 处理逻辑
}
// 安全获取对象长度
int len = ObjUtil.length(obj);
// 安全判断对象是否为空
if (ObjUtil.isNotEmpty(obj)) {
// 处理逻辑
}
# 2. 优雅的默认值处理
在处理可能为null的对象时,可以使用ObjUtil提供的默认值处理方法,使代码更加优雅:
// 传统方式
String name = user.getName();
if (name == null) {
name = "未知用户";
}
// 使用ObjUtil
String name = ObjUtil.defaultIfNull(user.getName(), "未知用户");
# 3. 灵活的对象处理
使用apply和accept方法,可以更加灵活地处理对象:
// 传统方式
if (user != null) {
String upperName = user.getName().toUpperCase();
Console.log(upperName);
}
// 使用ObjUtil
ObjUtil.accept(user, u -> {
String upperName = u.getName().toUpperCase();
Console.log(upperName);
});
// 使用apply进行转换
String result = ObjUtil.apply(user, u -> u.getName().toUpperCase());
# 4. 对象克隆
在需要对象副本时,可以使用ObjUtil的克隆方法:
// 浅克隆
Person personCopy = ObjUtil.clone(person);
// 深克隆
Person deepCopy = ObjUtil.cloneByStream(person);
// 安全克隆(失败返回原对象)
Person safeCopy = ObjUtil.cloneIfPossible(person);
# 5. 集合和数组操作
ObjUtil提供了统一的方式来操作不同类型的集合和数组:
// 统一计算长度
int strLen = ObjUtil.length("hello");
int listLen = ObjUtil.length(list);
int arrLen = ObjUtil.length(array);
int mapLen = ObjUtil.length(map);
// 统一判断包含关系
boolean strContains = ObjUtil.contains("hello", "ell");
boolean listContains = ObjUtil.contains(list, element);
boolean arrContains = ObjUtil.contains(array, element);
boolean mapContains = ObjUtil.contains(map, value);
# 注意事项
- 数组操作:
ObjUtil中的数组相关操作已经被标记为过时,建议使用ArrayUtil类来处理数组。 - 克隆限制:
- 实现
Cloneable接口的对象才能使用clone()方法进行浅克隆 - 实现
Serializable接口的对象才能使用cloneByStream()方法进行深克隆 - 对于复杂对象,建议使用序列化克隆来确保深克隆的正确性
- 实现
- 泛型参数获取:获取泛型参数类型依赖于运行时类型信息,对于类型擦除的情况可能无法正确获取
- 性能考虑:
length()方法对于迭代器和Enumeration类型会消耗掉元素,后续无法再次遍历- 序列化克隆的性能相对较低,仅在需要深克隆时使用
- 数值比较:
equals()方法对于数字类型的比较使用了NumberUtil.equals(),会处理不同数值类型之间的比较
# 总结
ObjUtil是一个功能全面的对象工具类,提供了丰富的对象操作方法,可以帮助开发者简化代码,提高开发效率。无论是对象比较、空值处理、默认值设置还是对象克隆,ObjUtil都提供了简洁易用的解决方案。在Java开发中,合理使用ObjUtil可以减少样板代码,避免常见的异常,使代码更加优雅和健壮。