news 2026/2/3 4:47:51

UtilEmpty空值检查工具类

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UtilEmpty空值检查工具类

* 提供高效、标准的空值检查功能。
* 支持 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; } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/3 1:01:20

Android启动镜像编辑器:5个关键步骤掌握镜像修改技巧

Android启动镜像编辑器&#xff1a;5个关键步骤掌握镜像修改技巧 【免费下载链接】Android_boot_image_editor Parsing and re-packing Android boot.img/vbmeta.img/payload.bin, supporting Android 13 项目地址: https://gitcode.com/gh_mirrors/an/Android_boot_image_ed…

作者头像 李华
网站建设 2026/2/2 23:08:36

Lucky Gold:2025年12月12日黄金关键事件汇总

今日凌晨&#xff0c;乌克兰无人机在里海实施袭击&#xff0c;目标为俄罗斯卢克石油公司的“菲拉诺夫斯基钻井平台”&#xff0c;致20余口井停产&#xff0c;该平台日产量约12万桶。乌方旨在持续削弱俄能源出口能力&#xff1b;据《华尔街日报》&#xff0c;特朗普的乌克兰和平…

作者头像 李华
网站建设 2026/2/2 23:08:41

UniBest跨端开发框架完整安装配置指南:从零开始构建多平台应用

UniBest跨端开发框架完整安装配置指南&#xff1a;从零开始构建多平台应用 【免费下载链接】unibest unibest - 最好用的 uniapp 开发框架。unibest 是由 uniapp Vue3 Ts Vite4 UnoCss UniUI 驱动的跨端快速启动模板&#xff0c;使用 VS Code 开发&#xff0c;具有代码提示…

作者头像 李华
网站建设 2026/2/3 0:06:54

如何完整解决Cursor试用限制问题:技术实现与操作指南

如何完整解决Cursor试用限制问题&#xff1a;技术实现与操作指南 【免费下载链接】go-cursor-help 解决Cursor在免费订阅期间出现以下提示的问题: Youve reached your trial request limit. / Too many free trial accounts used on this machine. Please upgrade to pro. We h…

作者头像 李华