[TOC]
在开发过程中,通常都会定义大量的JavaBean,而后通过IDE去产生其属性的结构器、getter、setter、equals、hashcode、toString办法,当要减少属性或者对某个属性进行扭转时,比方命名、类型等,都须要从新去产生下面提到的这些办法。这样反复的劳动没有任何意义,Lombok外面的注解能够轻松解决这些问题。
- 官网地址:https://projectlombok.org/
- github地址:https://github.com/rzwitserlo...
lombok实现的原理:次要是通过形象语法树(AST),在编译解决后,对应到有其注解的类,那么注解编译器就会主动去对应我的项目中的注解对应到在lombok语法树中的注解文件,并通过主动编译对应来产生对应类中的getter或者setter办法,达到简化代码的目标
pom.xml增加lombok
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional></dependency>
@Getter @Setter注解
这一对注解从名字上就很好了解,用在成员变量后面,相当于为成员变量生成对应的get和set办法,同时还能够为生成的办法指定拜访修饰符,当然,默认为public,间接来看上面的简略的例子:
// 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;}
等价于
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; }}
@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注解
这个注解能够用在成员办法或者构造方法的参数后面,会主动产生一个对于此参数的非空查看,如果参数为空,则抛出一个空指针异样,举个例子来看看
public class RumenzNonNull { @Getter @Setter @NonNull private Integer id; @Getter @Setter @NonNull private String name;}
等价于
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; }}
@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
@ToStringpublic class RumenzToString { @Getter @Setter private Integer id; @Getter @Setter private String name; @Override public String toString() { return "RumenzToString{" + "id=" + id + ", name='" + name + '\'' + '}'; }}
- 等价于
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 + '\'' + '}'; }}
@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注解
@EqualsAndHashCodepublic class RumenzEqualsAndHashCode { @Getter @Setter private Integer id; @Getter @Setter private String name;}
等价于
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); }}
@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()办法。
@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() + ")"; }}
@GetMapping("/index4")public String index4(){ RumenzData of = RumenzData.of(); of.setName("入门小站"); String name = of.getName(); return name;}
@Cleanup注解
这个注解用在变量后面,能够保障此变量代表的资源会被主动敞开,默认是调用资源的close()办法,如果该资源有其它敞开办法,可应用@Cleanup(“methodName”)来指定要调用的办法,就用输入输出流来举个例子吧:
@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);}
等价于
@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在类上应用,它能够提供一个无参结构器
@NoArgsConstructorpublic class RumenzNoArgsConstructor { private Integer id; private String name;}
等价于
public class RumenzNoArgsConstructor { private Integer id; private String name; public RumenzNoArgsConstructor() { }}
@RequiredArgsConstructor注解
指定final的属性生成构造方法
@ToString@RequiredArgsConstructorpublic class RumenzRequiredArgsConstructor { private Integer id; private final String name;}
// 等价于
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@AllArgsConstructorpublic class RumenzAllArgsConstructor { private Integer id; private String name;}
//等价于
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办法。
@ToString@Valuepublic class RumenzValue { private Integer id; private String name;}
// 等价于
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)的模式指定抛出哪种异样,很简略的注解,间接看个例子:
@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);}
// 等价于
@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去锁住代码块,而不是办法,因为锁住代码块效率更高。
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("入门小站"); }}
// 等价于
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
@ToString@Builderpublic class RumenzBuilder { private Integer id; private String name;}
// 等价于
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 + ")"; } }}
@GetMapping("/index11")public String index11() { RumenzBuilder rb=RumenzBuilder.builder().id(1).name("入门小站").build(); return rb.toString();}
@SuperBuilder
当实体类有集成关系时,须要用@SuperBuilder,否则调用的.builder都会报错.
@Builder并不反对父类成员属性的结构,@SuperBuilder注解的呈现,就是用来解决这个问题。
应用@Builder或@SuperBuilder注解时,不会默认创立空参构造函数,如果你有额定应用空参构造函数或全参构造函数的需要,须要在子类和父类都加上以下注解:
本小结源码地址:
- GitHub:https://github.com/mifunc/spr...
- Gitee:https://gitee.com/rumenz/spri...
- https://rumenz.com/rumenbiji/...
介绍
- 我的博客 https://rumenz.com/ ,
- 我的工具箱 https://tooltt.com/
- 微信公众号:【入门小站】
- 关注【入门小站】回复【1001】获取 linux常用命令速查手册
- 关注【入门小站】回复【1003】获取 LeetCode题解【java语言实现】
- 关注【入门小站】回复【1004】获取 Java根底外围总结
- 关注【入门小站】回复【1009】获取 阿里巴巴Java开发手册