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 感謝


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM