【JAVA】判断对象是否为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

  • OK 大功告成!
    在这里插入图片描述
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值