zoukankan      html  css  js  c++  java
  • 聊聊使用lombok @Builder踩到的坑

    前言

    什么是lombok

    Lombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,用来消除Java类中的大量样板代码。

    对lombok不熟悉的朋友,可以阅读一下官方文档,再来看本文。官方文档如下

    https://projectlombok.org/

    正文

    我们先来看一个小例子


    提问: main函数会输出什么?

    答案:空指针异常

    Exception in thread "main" java.lang.NullPointerException
    	at com.github.lybgeek.msg.test.User.addPositionList(User.java:25)
    	at com.github.lybgeek.msg.test.User.main(User.java:30)
    

    回答出正确答案的朋友,下文基本上可以不用看了。可能有些朋友会有疑问,我例子中明明使用了

      private List<String> positionList = new ArrayList<>();
    

    为什么还会报空指针?

    真相就在lombok用@builder生成的class文件中,我们看下使用@builder,生成的class文件反编译后长啥样


    看到我圈红起来的,大家应该就一目了然。原来当我们用

     User user = User.builder().username("张三").build();
    

    时,此时user对象中的positionList就会被userBuilder中的positionList覆盖,而userBuilder中的positionList是null

    如何解决

    方法一:positionList前面加上final修饰

      private final List<String> positionList = new ArrayList<>();
    

    此时用@Budiler生成class为

    此时user对象中的positionList用的还是原先的positionList,因此不会出现空指针异常

    方法二:positionList前面加上@Builder.Default注解

     @Builder.Default
     private List<String> positionList = new ArrayList<>();
    

    此时用@Budiler生成class为

     public static class UserBuilder {
            private String username;
            private boolean positionList$set;
            private List<String> positionList;
    
            UserBuilder() {
            }
    
            public User.UserBuilder username(final String username) {
                this.username = username;
                return this;
            }
    
            public User.UserBuilder positionList(final List<String> positionList) {
                this.positionList = positionList;
                this.positionList$set = true;
                return this;
            }
    
            public User build() {
                List<String> positionList = this.positionList;
                if (!this.positionList$set) {
                    positionList = User.$default$positionList();
                }
    
                return new User(this.username, positionList);
            }
    
    

    当positionList$set为false,会给userBuilder的positionList赋值为

    User.$default$positionList();
    即:
      private static List<String> $default$positionList() {
            return new ArrayList();
        }
    
    

    因此当user对象中的positionList被userBuilder中的positionList覆盖后,userBuilder中的positionList是new ArrayList(),此时就不会出现空指针现象

    方法三:不用build实例化对象

     User user = User.builder().username("张三").build();
    

    改成用

    User user = new User();
    user.setUsername("张三");
    user.addPositionList("经理");
    

    总结

    很多时候没那么多的想当然

  • 相关阅读:
    android gallery 自定义边框+幻灯片
    C/C++学习笔记---高地址、低地址、大段字节序、小段字节序
    C#学习笔记--详解委托,事件与回调函数
    Clr Via C#读书笔记---计算限制的异步操作
    Clr Via C#读书笔记---CLR寄宿和应用程序域
    Clr Via C#读书笔记---程序集的加载和反射
    Clr Via C#读书笔记---垃圾回收机制
    Clr Via C#读书笔记---线程基础
    CLR via C#(18)——Enum
    CLR via C#(17)--接口
  • 原文地址:https://www.cnblogs.com/linyb-geek/p/15266311.html
Copyright © 2011-2022 走看看