* 提供高效、标准的空值检查功能。
* 支持 POJO 对象的递归字段检查(作为最后优先级。
import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; /** * 空值检查工具类 * <p> * 提供高效、标准的空值检查功能。 * 支持 POJO 对象的递归字段检查(作为最后优先级),并针对 JDK 内置对象进行优化。 * </p> * * @author LXD * @version 1.0.1 */ public final class UtilEmpty { /** * 缓存字段信息,避免重复反射调用 */ private static final ClassValue<Field[]> FIELD_CACHE = new ClassValue<Field[]>() { @Override protected Field[] computeValue(Class<?> type) { List<Field> fields = new ArrayList<>(); // 获取所有声明的字段,包括私有字段 for (Field field : type.getDeclaredFields()) { // 排除静态字段和 transient 字段 if (!Modifier.isStatic(field.getModifiers()) && !Modifier.isTransient(field.getModifiers())) { try { field.setAccessible(true); fields.add(field); } catch (Exception ignored) { // 忽略无法设置访问权限的字段(如模块系统限制) } } } return fields.toArray(new Field[0]); } }; /** * 私有构造函数,防止实例化 */ private UtilEmpty() { throw new UnsupportedOperationException("Utility class"); } // ================================================================================= // 核心判空方法 (Overloads for Performance) // ================================================================================= /** * 检查字符串是否为空 * * @param str 字符串 * @return 如果字符串为 null 或仅包含空白字符,则返回 true */ public static boolean isNull(String str) { return isBlank(str); } /** * 检查集合是否为空 * * @param collection 集合 * @return 如果集合为 null 或不包含元素,则返回 true */ public static boolean isNull(Collection<?> collection) { return collection == null || collection.isEmpty(); } /** * 检查 Map 是否为空 * * @param map Map * @return 如果 Map 为 null 或不包含映射,则返回 true */ public static boolean isNull(Map<?, ?> map) { return map == null || map.isEmpty(); } /** * 检查对象数组是否为空 * * @param array 数组 * @return 如果数组为 null 或长度为 0,则返回 true */ public static boolean isNull(Object[] array) { return array == null || array.length == 0; } /** * 检查数值是否为 null (注意:0 不会被视为 null) * * @param number 数值 * @return 如果数值为 null,则返回 true */ public static boolean isNull(Number number) { return number == null; } /** * 检查布尔值是否为 null (注意:false 不会被视为 null) * * @param bool 布尔值 * @return 如果布尔值为 null,则返回 true */ public static boolean isNull(Boolean bool) { return bool == null; } // ================================================================================= // 通用判空方法 // ================================================================================= /** * 检查对象是否为空 * <p> * 规则:<br> * 1. null -> true <br> * 2. CharSequence -> 仅包含空白字符时为 true<br> * 3. Collection/Map -> isEmpty() 为 true<br> * 4. Array -> length == 0 为 true<br> * 5. Optional -> !isPresent() 为 true<br> * 6. Iterator/Iterable -> !hasNext() 为 true<br> * 7. 其他对象 (POJO) -> 递归检查所有字段,若所有字段均为空则返回 true<br> * 注意:java.* 和 javax.* 开头的类被视为值对象,只要不为 null 即视为不为空<br> * </p> * * @param object 要检查的对象 * @return 如果对象符合上述空值规则,则返回 true */ public static boolean isNull(Object object) { if (object == null) { return true; } // 优先检查最常见的类型 if (object instanceof String) { return isBlank((String) object); } if (object instanceof Collection) { return ((Collection<?>) object).isEmpty(); } if (object instanceof Map) { return ((Map<?, ?>) object).isEmpty(); } if (object instanceof Object[]) { return ((Object[]) object).length == 0; } // 处理其他特定类型 if (object instanceof CharSequence) { return isBlank((CharSequence) object); } // 原始类型数组处理 (int[], byte[] 等) Class<?> clazz = object.getClass(); if (clazz.isArray()) { return Array.getLength(object) == 0; } if (object instanceof Optional) { return !((Optional<?>) object).isPresent(); } if (object instanceof Iterable) { return !((Iterable<?>) object).iterator().hasNext(); } if (object instanceof Iterator) { return !((Iterator<?>) object).hasNext(); } // 基本类型包装类、Number、Boolean、Date 等通常被视为值对象,不应被递归检查 // 为了安全和性能,跳过 JDK 内部类的反射检查 String className = clazz.getName(); if (className.startsWith("java.") || className.startsWith("javax.")) { return false; } // POJO 反射检查 (作为最后手段) return isPojoEmpty(object, clazz); } // ================================================================================= // 扩展辅助方法 // ================================================================================= /** * 检查对象是否不为空 * * @param object 对象 * @return 如果对象不为空,则返回 true */ public static boolean isNotNull(Object object) { return !isNull(object); } /** * 检查数值是否为 null 或 0 * <p> * 适用于需要将 0 视为"空"的特定业务场景 * </p> * * @param number 数值 * @return 如果数值为 null 或 0,则返回 true */ public static boolean isNullOrZero(Number number) { if (number == null) { return true; } if (number instanceof BigDecimal) { return BigDecimal.ZERO.compareTo((BigDecimal) number) == 0; } if (number instanceof BigInteger) { return BigInteger.ZERO.compareTo((BigInteger) number) == 0; } if (number instanceof Double || number instanceof Float) { return number.doubleValue() == 0.0; } return number.longValue() == 0L; } // ================================================================================= // 私有实现细节 // ================================================================================= /** * 检查 POJO 对象是否所有字段都为空 * * @param object 对象实例 * @param clazz 对象类 * @return 如果所有字段都为空,则返回 true */ private static boolean isPojoEmpty(Object object, Class<?> clazz) { Field[] fields = FIELD_CACHE.get(clazz); if (fields.length == 0) { // 如果对象没有字段(且不是上述已知集合类型),则视为不为空(即它本身就是一个非空对象实例) return false; } for (Field field : fields) { try { Object value = field.get(object); // 只要有一个字段不为空,整个对象就不为空 if (!isNull(value)) { return false; } } catch (IllegalAccessException e) { // 理论上不会发生,因为在 cache 中已经 setAccessible(true) // 如果发生,为了安全起见,认为该字段不为空(保守策略)或忽略该字段 // 这里选择忽略该字段继续检查其他字段 } } // 所有字段都为空 return true; } /** * 检查 CharSequence 是否为空或空白 */ private static boolean isBlank(CharSequence cs) { int length; if (cs == null || (length = cs.length()) == 0) { return true; } for (int i = 0; i < length; i++) { if (!Character.isWhitespace(cs.charAt(i))) { return false; } } return true; } }