前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >第十三节:使用Lombok简化你的代码

第十三节:使用Lombok简化你的代码

原创
作者头像
入门笔记
修改2022-02-18 14:38:52
4780
修改2022-02-18 14:38:52
举报
文章被收录于专栏:入门小站入门小站

TOC

在开发过程中,通常都会定义大量的JavaBean,然后通过IDE去产生其属性的构造器、getter、setter、equals、hashcode、toString方法,当要增加属性或者对某个属性进行改变时,比如命名、类型等,都需要重新去产生上面提到的这些方法。这样重复的劳动没有任何意义,Lombok里面的注解可以轻松解决这些问题。

lombok实现的原理:主要是通过抽象语法树(AST),在编译处理后,对应到有其注解的类,那么注解编译器就会自动去对应项目中的注解对应到在lombok语法树中的注解文件,并经过自动编译对应来产生对应类中的getter或者setter方法,达到简化代码的目的

pom.xml添加lombok

代码语言:txt
复制
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <optional>true</optional>
</dependency>

@Getter @Setter注解

这一对注解从名字上就很好理解,用在成员变量前面,相当于为成员变量生成对应的get和set方法,同时还可以为生成的方法指定访问修饰符,当然,默认为public,直接来看下面的简单的例子:

代码语言:txt
复制
// Rumenz.java
/**
 * @className: Rumenz
 * @description: TODO 类描述
 * @author: 入门小站 rumenz.com
 * @date: 2021/12/9
 **/
public class RumenzGetSet {
    @Getter @Setter
    private Integer id;
    @Getter @Setter
    private String name;

}
  • 等价于
代码语言:javascript
复制
public class RumenzGetSet {
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
代码语言:txt
复制
@RestController
@RequestMapping("/rumenz")
public class RumenzController {

    @GetMapping("/index")
    public String index(){
        RumenzGetSet r=new RumenzGetSet();
        r.setId(1);
        r.setName("入门小站");

        return r.getId()+r.getName();
    }
}

访问http://127.0.0.1:8080/rumenz/index返回1入门小站

@NonNull注解

这个注解可以用在成员方法或者构造方法的参数前面,会自动产生一个关于此参数的非空检查,如果参数为空,则抛出一个空指针异常,举个例子来看看

代码语言:txt
复制
public class RumenzNonNull {
    @Getter @Setter @NonNull
    private Integer id;
    @Getter @Setter @NonNull
    private String name;
}
  • 等价于
代码语言:javascript
复制
public class RumenzNonNull {
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        if (id == null) throw new java.lang.NullPointerException("id");
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if (name == null) throw new java.lang.NullPointerException("name");
        this.name = name;
    }
}
代码语言:txt
复制
@GetMapping("/index1")
public String index1(){
    RumenzNonNull r=new RumenzNonNull();
    r.setId(1);
    r.setName(null);

    return r.getId()+r.getName();
}

访问http://127.0.0.1:8080/rumenz/index1报错java.lang.NullPointerException: name is marked non-null but is null

@ToString

代码语言:txt
复制
@ToString
public class RumenzToString {

    @Getter @Setter
    private Integer id;

    @Getter @Setter
    private String name;

    @Override
    public String toString() {
        return "RumenzToString{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
  • 等价于
代码语言:txt
复制
public class RumenzToString {

    private Integer id;

    private String name;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "RumenzToString{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
代码语言:txt
复制
@GetMapping("/index2")
public String index2(){
     RumenzToString r=new RumenzToString();
     r.setId(1);
     r.setName("入门小站");
     return r.toString();
}

访问http://127.0.0.1:8080/rumenz/index1返回RumenzToString{id=1, name='入门小站'}

EqualsAndHashCode注解

代码语言:txt
复制
@EqualsAndHashCode
public class RumenzEqualsAndHashCode {

    @Getter @Setter
    private Integer id;
    @Getter @Setter
    private String name;

}
  • 等价于
代码语言:javascript
复制
public class RumenzEqualsAndHashCode {
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof RumenzEqualsAndHashCode)) return false;
        RumenzEqualsAndHashCode that = (RumenzEqualsAndHashCode) o;
        return id.equals(that.id) &&
                name.equals(that.name);
    }

}
代码语言:txt
复制
@GetMapping("/index3")
public String index3(){
    RumenzEqualsAndHashCode r1=new RumenzEqualsAndHashCode();
    r1.setId(1);
    r1.setName("入门小站");

    RumenzEqualsAndHashCode r2=new RumenzEqualsAndHashCode();
    r2.setId(1);
    r2.setName("入门小站");
    if(r1.equals(r2)){
    return "相等";
    }
    return "不相等";
}

@Data注解

  • 1)生成无参构造方法;
  • 2)属性的set/get方法;
  • 3)equals(), hashCode(), toString(), canEqual()方法。
代码语言:txt
复制
@Data(staticConstructor="of")
public class RumenzData {


    private Integer id;

    private String name;

}
//等价于

public class RumenzData {
    private Integer id;
    private String name;

    private RumenzData() {
    }

    public static RumenzData of() {
        return new RumenzData();
    }

    public Integer getId() {
        return this.id;
    }

    public String getName() {
        return this.name;
    }

    public void setId(final Integer id) {
        this.id = id;
    }

    public void setName(final String name) {
        this.name = name;
    }

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof RumenzData)) {
            return false;
        } else {
            RumenzData other = (RumenzData)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                Object this$id = this.getId();
                Object other$id = other.getId();
                if (this$id == null) {
                    if (other$id != null) {
                        return false;
                    }
                } else if (!this$id.equals(other$id)) {
                    return false;
                }

                Object this$name = this.getName();
                Object other$name = other.getName();
                if (this$name == null) {
                    if (other$name != null) {
                        return false;
                    }
                } else if (!this$name.equals(other$name)) {
                    return false;
                }

                return true;
            }
        }
    }

    protected boolean canEqual(final Object other) {
        return other instanceof RumenzData;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $id = this.getId();
        int result = result * 59 + ($id == null ? 43 : $id.hashCode());
        Object $name = this.getName();
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }

    public String toString() {
        return "RumenzData(id=" + this.getId() + ", name=" + this.getName() + ")";
    }
}
代码语言:txt
复制
@GetMapping("/index4")
public String index4(){
   RumenzData of = RumenzData.of();
   of.setName("入门小站");
   String name = of.getName();
   return name;
}

@Cleanup注解

这个注解用在变量前面,可以保证此变量代表的资源会被自动关闭,默认是调用资源的close()方法,如果该资源有其它关闭方法,可使用@Cleanup(“methodName”)来指定要调用的方法,就用输入输出流来举个例子吧:

代码语言:txt
复制
@GetMapping("/index5")
public String index5() throws IOException {

   File file = ResourceUtils.getFile("classpath:application.properties");
   @Cleanup  InputStream inputStream = new FileInputStream(file);

   byte b[]=new byte[(int) file.length()];
   inputStream.read(b);
   //@Cleanup 代替了 inputStream.close();
   return new String(b);
}

等价于

代码语言:txt
复制
@GetMapping({"/index5"})
public String index5() throws IOException {
        File file = ResourceUtils.getFile("classpath:application.properties");
        FileInputStream inputStream = new FileInputStream(file);

        String var4;
        try {
            byte[] b = new byte[(int)file.length()];
            inputStream.read(b);
            var4 = new String(b);
        } finally {
            if (Collections.singletonList(inputStream).get(0) != null) {
                inputStream.close();
            }

        }

        return var4;
}

@NoArgsConstructor注解

@NoArgsConstructor在类上使用,它可以提供一个无参构造器

代码语言:txt
复制
@NoArgsConstructor
public class RumenzNoArgsConstructor {
    private Integer id;
    private String name;
}

等价于

代码语言:txt
复制
public class RumenzNoArgsConstructor {
    private Integer id;
    private String name;

    public RumenzNoArgsConstructor() {
    }
}

@RequiredArgsConstructor注解

指定final的属性生成构造方法

代码语言:txt
复制
@ToString
@RequiredArgsConstructor
public class RumenzRequiredArgsConstructor {
    private Integer id;
    private final String name;
}

// 等价于

代码语言:txt
复制
public class RumenzRequiredArgsConstructor {
    private Integer id;
    private final String name; //final

    public String toString() {
        return "RumenzRequiredArgsConstructor(id=" + this.id + ", name=" + this.name + ")";
    }

    public RumenzRequiredArgsConstructor(final String name) {
        this.name = name;
    }
}

@AllArgsConstructor注解

类中所有的字段都生成一个有参的构造方法.@ToString @AllArgsConstructor public class RumenzAllArgsConstructor { private Integer id; private String name; }

//等价于

代码语言:txt
复制
public class RumenzAllArgsConstructor {
    private Integer id;
    private String name;

    public String toString() {
        return "RumenzAllArgsConstructor(id=" + this.id + ", name=" + this.name + ")";
    }

    public RumenzAllArgsConstructor(final Integer id, final String name) {
        this.id = id;
        this.name = name;
    }
}

@Value注解

  • 1)有参构造方法;
  • 2)只添加@Value注解,没有其他限制,那么类属性会被编译成final的,因此只有get方法,而没有set方法。
代码语言:txt
复制
@ToString
@Value
public class RumenzValue {
    private Integer id;
    private String name;
}

// 等价于

代码语言:txt
复制
public final class RumenzValue {
    private final Integer id;
    private final String name;

    public RumenzValue(final Integer id, final String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return this.id;
    }

    public String getName() {
        return this.name;
    }

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof RumenzValue)) {
            return false;
        } else {
            RumenzValue other = (RumenzValue)o;
            Object this$id = this.getId();
            Object other$id = other.getId();
            if (this$id == null) {
                if (other$id != null) {
                    return false;
                }
            } else if (!this$id.equals(other$id)) {
                return false;
            }

            Object this$name = this.getName();
            Object other$name = other.getName();
            if (this$name == null) {
                if (other$name != null) {
                    return false;
                }
            } else if (!this$name.equals(other$name)) {
                return false;
            }

            return true;
        }
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $id = this.getId();
        int result = result * 59 + ($id == null ? 43 : $id.hashCode());
        Object $name = this.getName();
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }

    public String toString() {
        return "RumenzValue(id=" + this.getId() + ", name=" + this.getName() + ")";
    }
}

@SneakyThrows注解

这个注解用在方法上,可以将方法中的代码用try-catch语句包裹起来,捕获异常并在catch中用Lombok.sneakyThrow(e)把异常抛出,可以使用@SneakyThrows(Exception.class)的形式指定抛出哪种异常,很简单的注解,直接看个例子:

代码语言:txt
复制
@SneakyThrows
@GetMapping("/index9")
public String index9() {

        //使用@SneakyThrows就不用显式抛出异常了
        File file = ResourceUtils.getFile("classpath:application.properties");
        @Cleanup  InputStream inputStream = new FileInputStream(file);

        byte b[]=new byte[(int) file.length()];
        inputStream.read(b);
        //@Cleanup 代替了 inputStream.close();
        return new String(b);
}

// 等价于

代码语言:txt
复制
@GetMapping({"/index9"})
public String index9() {
        try {
            File file = ResourceUtils.getFile("classpath:application.properties");
            FileInputStream inputStream = new FileInputStream(file);

            String var4;
            try {
                byte[] b = new byte[(int)file.length()];
                inputStream.read(b);
                var4 = new String(b);
            } finally {
                if (Collections.singletonList(inputStream).get(0) != null) {
                    inputStream.close();
                }

            }

            return var4;
        } catch (Throwable var9) {
            throw var9;
        }
}

@Synchronized注解

synchronized是线程安全中一个重要的关键字,它是一种同步锁,主要用来保证在同一个时刻,只有一个线程可以执行某个方法或者某段代码块。一般使用synchronized去锁住代码块,而不是方法,因为锁住代码块效率更高。

代码语言:txt
复制
public class RumenzSynchronized {

    private final Object readLock = new Object();

    @Synchronized
    public static void hello() {
        System.out.println("rumenz.com");
    }

    @Synchronized
    public int answerToLife() {
        return 110;
    }

    @Synchronized("readLock")
    public void foo() {
        System.out.println("入门小站");
    }
}

// 等价于

代码语言:txt
复制
public class RumenzSynchronized {
    private static final Object $LOCK = new Object[0];
    private final Object $lock = new Object[0];
    private final Object readLock = new Object();

    public RumenzSynchronized() {
    }

    public static void hello() {
        synchronized($LOCK) {
            System.out.println("rumenz.com");
        }
    }

    public int answerToLife() {
        synchronized(this.$lock) {
            return 110;
        }
    }

    public void foo() {
        synchronized(this.readLock) {
            System.out.println("入门小站");
        }
    }
}

@Builder注解

用在类、构造器、方法上,为你提供复杂的builder APIs

代码语言:txt
复制
@ToString
@Builder
public class RumenzBuilder {
    private Integer id;
    private String name;
}

// 等价于

代码语言:txt
复制
public class RumenzBuilder {
    private Integer id;
    private String name;

    RumenzBuilder(final Integer id, final String name) {
        this.id = id;
        this.name = name;
    }

    public static RumenzBuilder.RumenzBuilderBuilder builder() {
        return new RumenzBuilder.RumenzBuilderBuilder();
    }

    public String toString() {
        return "RumenzBuilder(id=" + this.id + ", name=" + this.name + ")";
    }

    public static class RumenzBuilderBuilder {
        private Integer id;
        private String name;

        RumenzBuilderBuilder() {
        }

        public RumenzBuilder.RumenzBuilderBuilder id(final Integer id) {
            this.id = id;
            return this;
        }

        public RumenzBuilder.RumenzBuilderBuilder name(final String name) {
            this.name = name;
            return this;
        }

        public RumenzBuilder build() {
            return new RumenzBuilder(this.id, this.name);
        }

        public String toString() {
            return "RumenzBuilder.RumenzBuilderBuilder(id=" + this.id + ", name=" + this.name + ")";
        }
    }
}
代码语言:txt
复制
@GetMapping("/index11")
public String index11() {
    RumenzBuilder rb=RumenzBuilder.builder().id(1).name("入门小站").build();
    return rb.toString();
}

@SuperBuilder

当实体类有集成关系时,需要用@SuperBuilder,否则调用的.builder都会报错.

@Builder并不支持父类成员属性的构造,@SuperBuilder注解的出现,就是用来解决这个问题。

使用@Builder或@SuperBuilder注解时,不会默认创建空参构造函数,如果你有额外使用空参构造函数或全参构造函数的需求,需要在子类和父类都加上以下注解:

本小结源码地址:

介绍

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • pom.xml添加lombok
    • @Getter @Setter注解
      • @NonNull注解
        • @ToString
          • EqualsAndHashCode注解
            • @Data注解
              • @Cleanup注解
                • @NoArgsConstructor注解
                  • @RequiredArgsConstructor注解
                    • @AllArgsConstructor注解
                      • @Value注解
                        • @SneakyThrows注解
                          • @Synchronized注解
                            • @Builder注解
                              • @SuperBuilder
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档