java对象属性没有值为什么不是null,判断对象是否为null,包括对象中的属性为null,可自定义判断的属性或值
前言
java中当对象需要判空的时候,大体都会直接 if(Object != null) ,而当我们的对象是 new Object()的时候,往往这种判断不会起作用
因为此时对象已经被实例化,所以在项目中通常会用反射获取Field从而判断该属性值是否为null,也就是常说的判断对象中所有属性不为null,本文讲讲我在项目中利用反射来判断遇到的问题和一些坑
编写工具类解决我们的问题
- 废话不说,上代码
/** * description:定义一个System.out.println的开(纯属个人习惯) **/ private static int objectNullSystemOutFlag = 0; /** * description:判断当前对象是否为空(包括所有属性为空) * * @author ZhangXihui * @param object 入参类 * @return boolean * @create 2019/6/3 17:34 **/ public static boolean objCheckIsNull(Object object) { if (object == null) { return true; } // 得到类对象 Class clazz = object.getClass(); // 得到所有属性 Field[] fields = clazz.getDeclaredFields(); //定义返回结果,默认为true boolean flag = true; for (Field field : fields) { //设置权限(很重要,否则获取不到private的属性,不了解的同学补习一下反射知识) field.setAccessible(true); Object fieldValue = null; String fieldName = null; try { //得到属性值 fieldValue = field.get(object); //得到属性类型 Type fieldType = field.getGenericType(); //得到属性名 fieldName = field.getName(); //打印输出(调试用可忽略) if (objectNullSystemOutFlag == 1) { System.out.println("属性类型:" + fieldType + ",属性名:" + fieldName + ",属性值:" + fieldValue); } } catch (IllegalArgumentException | IllegalAccessException e) { e.printStackTrace(); } //只要有一个属性值不为null 就返回false 表示对象不为null if (fieldValue != null) { flag = false; break; } } return flag; }
- 简单的写一个main,我们开始测试
-
public static void main(String[] args) { @ToString class User { private String username; private String password; public User() { } public User(String username, String password) { this.username = username; this.password = password; } } User user = new User(); System.out.println(user); //正常判断 System.out.println(user == null); //使用反射的工具类 System.out.println( CommonFunction.objCheckIsNull(user)); }
- 输出结果
-
User(username=null, password=null) false true
- 可见我们的工具类是好用的,但是在使用中会遇到一些问题,接下来说说我项目中遇到的问题和解决方法
问题与解决
- 场景一:在web开发中,实体类我们经常会进行序列化, implements Serializable 并为其添加一个 serialVersionUID
-
@ToString class User implements Serializable { private static final long serialVersionUID = 1996598449318251880L; private String username; private String password; public User() { } public User(String username, String password) { this.username = username; this.password = password; } }
-
产生问题:可以看到 serialVersionUID 是作为类中的一个属性,而最开始构建的工具类没有考虑到serialVersionUID 的存在
这样会导致其返回结果一直为false,这也是一开始困扰我的原因,当我们专注于某一件事的时候,往往会忽略一些事情。解决:在判断条件中忽略序列化字段名
//只要有一个属性值不为null 就返回false 表示对象不为null 忽略序列化 if (fieldValue != null && !"serialVersionUID".equals(fieldName)) { flag = false; break; }
-
场景二:
业务需求场景:有一入参实体类,该实体类有30个属性,其中有2个属性会在程序中赋予默认值为10,这样就导致该类有28个为null的属性和2个为10的属性,业务判断为:除了默认值的两个属性之外如果所有属性为null,那么我们就认为这个入参实体类什么也没接到,也就认为它为"空"。
那么问题来了,难道我们要去挨个判断剩余的28个字段为空么?很显然不是的,根据上面我们从属性判断中剔除 serialVersionUID 的思路出发,我们会发现,业务中会经常出现,我们希望判断某一实体类中,除了某些属性或者某些值之外的属性为null的情况,也就是我们判空的时候希望剔除掉某些属性或者某些值,so,基于这些场景我改造了工具类,使其能够实现我们的思路
-
/** * description:判断当前对象是否为空(包括所有属性为空) * 可选则在判断规则中剔除某一字段,或者某一值 * * @author ZhangXihui * @param object 入参对象 * @param excludeNameList 要剔除的属性名称,没有就传空集合或者null * @param excludeValueList 要剔除的数值,没有就传空集合或者null * @return boolean * @create 2019/6/3 17:34 **/ public static boolean objCheckIsNull(Object object, List<String> excludeNameList, List<Object> excludeValueList) { if (object == null) { return true; } // 得到类对象 Class clazz = object.getClass(); // 得到所有属性 Field[] fields = clazz.getDeclaredFields(); //判断入参 boolean excludeNameListFlag = false; if (excludeNameList != null && excludeNameList.size() > 0) { excludeNameListFlag = true; } boolean excludeValueListFlag = false; if (excludeValueList != null && excludeValueList.size() > 0) { excludeValueListFlag = true; } //定义返回结果,默认为true boolean flag = true; for (Field field : fields) { field.setAccessible(true); Object fieldValue = null; String fieldName = null; try { //得到属性值 fieldValue = field.get(object); //得到属性类型 Type fieldType = field.getGenericType(); //得到属性名 fieldName = field.getName(); //剔除指定属性名的属性值 if (excludeNameListFlag) { for (String s : excludeNameList) { if (fieldName.equals(s)) { fieldValue = null; break; } } } //剔除指定属性值 if (excludeValueListFlag) { for (Object obj : excludeValueList) { if (obj.equals(fieldValue)) { fieldValue = null; break; } } } //打印输出(调试用可忽略) if (objectNullSystemOutFlag == 1) { System.out.println("属性类型:" + fieldType + ",属性名:" + fieldName + ",属性值:" + fieldValue); } } catch (IllegalArgumentException | IllegalAccessException e) { e.printStackTrace(); } //只要有一个属性值不为null 就返回false 表示对象不为null 忽略序列化 if (fieldValue != null && !"serialVersionUID".equals(fieldName)) { flag = false; break; } } //打印输出(调试用可忽略) if (objectNullSystemOutFlag == 1) { System.out.println("忽略属性: " + excludeNameList + " 忽略值: " + excludeValueList); } return flag; }
- 测试一下
-
public static void main(String[] args) { @ToString class User implements Serializable { private static final long serialVersionUID = 1996598449318251880L; private String username; private String password; private String sex; private String childSex; public User() { } public User(String sex, String childSex) { this.sex = sex; this.childSex = childSex; } } User user = new User("男性","男性"); System.out.println(user); //使用基础的反射工具类 System.out.println( CommonFunction.objCheckIsNull(user)); //在判断中剔除 value 为男性的属性 System.out.println( CommonFunction.objCheckIsNull(user,null, Collections.singletonList("男性"))); //在判断中剔除 属性名 为 sex,childSex 的属性 System.out.println( CommonFunction.objCheckIsNull(user,Arrays.asList("sex","childSex"),null)); }
- 结果
User(username=null, password=null, sex=男性, childSex=男性) false true true
- 成功
参考链接https://blog.csdn.net/qq_35566813/article/details/90914062 感谢