美文网首页
【lombok】Boolean类型属性兼容原始get/set方法

【lombok】Boolean类型属性兼容原始get/set方法

作者: 7ccc099f4608 | 来源:发表于2018-07-12 21:17 被阅读942次

    兼容性问题产生于lombok 1.16.18,没有测试过后续版本。

    解决方案(问题的出现和分析看后文)

    1. 将lombok要序列化的Boolean属性,使用@JSONField注解,指定序列化后的名字为截去is后名字(首字母大小写不敏感),比如isHeheda注解为@JSONField(name = "heheda"),或者@JSONField(name = "Heheda")
    2. 手动/使用IDEA半自动显示地为Boolean属性加上gettersetter方法;
    3. 终极解决方案, 不要用is作为开头的方式来表征这是一个Boolean型属性。old school的作风有时候会害死人的。。。
    package javaFirstJson;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.annotation.JSONField;
    import lombok.Data;
    
    @Data
    class useLombok {
        private Long id;
    
        // 方法一:
        @JSONField(name = "heheda")  // 指定序列化之后的字段名,序列化时区分大小写;反序列化时不区分大小写
        private Boolean isHeheda = false;
    
        // 方法二:
    //    public Boolean getHeheda() {
    //        return isHeheda;
    //    }
    //
    //    public void setHeheda(Boolean heheda) {
    //        isHeheda = heheda;
    //    }
    
    }
    
    class defaultGetSet {
        private Long id;
        private Boolean isHeheda = false;
    
        public Boolean getHeheda() {
            return isHeheda;
        }
    
        public void setHeheda(Boolean heheda) {
            isHeheda = heheda;
        }
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    }
    
    public class DiffLombokAndSet {
        public static void main(String[] args) {
            useLombok ul = new useLombok();
            ul.setIsHeheda(true);
            System.out.println("lombok 序列化:");
            System.out.println(JSON.toJSONString(ul));
    
            defaultGetSet df = new defaultGetSet();
            df.setHeheda(true);
            System.out.println("默认getter/setter 序列化:");
            System.out.println(JSON.toJSONString(df));
    
    
            String withIs = "{\"isHeheda\":true}";
            String withoutIs = "{\"heheda\":true}";
    
            System.out.println("使用lombok,反序列化");
            System.out.println(JSON.parseObject(withIs, useLombok.class));   // true
            System.out.println(JSON.parseObject(withoutIs, useLombok.class).getIsHeheda());  // false
    
            System.out.println("使用默认getter、setter,反序列化");
            System.out.println(JSON.parseObject(withIs, defaultGetSet.class).getHeheda());  // true
            System.out.println(JSON.parseObject(withoutIs, defaultGetSet.class).getHeheda());  // true
    
            /** 使用lombok, 序列化boolean, 会出现 `isSomeField`;
             *  而使用默认的getter、setter,则是someField */
    
            /** fastJson 1.2.41, lombok 1.16.18,
             * lombok反序列化Boolean类型时,无法自动关联 没有is的字符串 和 有is的字段 */
        }
    }
    

    输出:

    lombok 序列化:
    {"heheda":true}
    默认getter/setter 序列化:
    {"heheda":true}
    使用lombok,反序列化
    useLombok(id=null, isHeheda=true)
    true
    使用默认getter、setter,反序列化
    true
    true
    

    前言

    lombok 插件让生活简化了不少,一个@Data免去了一次次对每一个变量输入Alt+Enter,生成gettersetter的麻烦。然鹅,当类中有Boolean型属性,且命名为isHeheda 时,新老代码兼容问题,真的让人呵呵哒。

    使用lombok让生活更美好

    生成同一个类

    1. 使用lombok插件:
    import lombok.Data;
    
    @Data
    class useLombok {
        private Long id;
        private Boolean isHeheda = false;
    }
    
    1. 默认getter/setter方法
    class defaultGetSet {
        private Long id;
        private Boolean isHeheda = false;
    
        public Boolean getHeheda() {
            return isHeheda;
        }
    
        public void setHeheda(Boolean heheda) {
            isHeheda = heheda;
        }
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    }
    

    显而易见,在实现同样功能的情况下,传统的getter/setter方法有点反人类,即使是IDEA能半自动的加上,仍然很不方便。

    但是

    两种方法看似相同,但是当有Boolean类型的属性时……

            useLombok ul = new useLombok();
            ul.setIsHeheda(true);
            System.out.println("lombok 序列化:");
            System.out.println(JSON.toJSONString(ul));
    
            defaultGetSet df = new defaultGetSet();
            df.setHeheda(true);
            System.out.println("默认getter/setter 序列化:");
            System.out.println(JSON.toJSONString(df));
    

    输出:

    lombok 序列化:
    {"isHeheda":true}
    默认getter/setter 序列化:
    {"heheda":true}
    

    看出差别没?

    1. lombok调用set方法时,严格按照Xxx改成setXxx;虽然传统方法大体也是如此,但是当有Boolean类型,且字段名是isXxx时,却将is自动截去,变成了setXxx
    2. 序列化后,lombok生成的是原字段,包括布尔类型的isHeheda;而传统方法,则将布尔类型的isHeheda序列化成"heheda"。

    如果,序列化后的结果不影响反序列化,那么,这些差异可以直接忽略

    BUT
            String withIs = "{\"isHeheda\":true}";
            String withoutIs = "{\"heheda\":true}";
    
            System.out.println("使用lombok,反序列化");
            System.out.println(JSON.parseObject(withIs, useLombok.class));   // true
            System.out.println(JSON.parseObject(withoutIs, useLombok.class).getIsHeheda());  // false
    
            System.out.println("使用默认getter、setter,反序列化");
            System.out.println(JSON.parseObject(withIs, defaultGetSet.class).getHeheda());  // true
            System.out.println(JSON.parseObject(withoutIs, defaultGetSet.class).getHeheda());  // true
    

    输出:

    使用lombok,反序列化
    useLombok(id=null, isHeheda=true)
    false
    使用默认getter、setter,反序列化
    true
    true
    

    可以看出:

    1. 传统方法的兼容性很强,无论字符串里面的是isHeheda 还是"heheda",都能反序列化成布尔类型的isHeheda
    2. lombok只能反序列化isHeheda,而由传统方法序列化成的"heheda"则不能序列化。

    因此,lombok和传统方法在序列化或者反序列化的时候,似乎不好混用。但是出于代码健壮性考虑,或者为了兼容前人代码,不得不考虑解决方案。

    相关文章

      网友评论

          本文标题:【lombok】Boolean类型属性兼容原始get/set方法

          本文链接:https://www.haomeiwen.com/subject/gizrpftx.html