title: lombok 简化 Java 代码
- date: 2018-10-20 20:32:19
- tags: lombok
author : 辰砂 tj
1. 介绍
Lombok 是一种 Java 实用工具, 可用来帮助开发人员消除 Java 的冗长, 尤其是对于简单的 Java 对象(POJO). 它通过注解实现这一目的. Lombok 官网: https://projectlombok.org
2.idea 使用
1. 引入依赖
在项目中添加 Lombok 依赖 jar, 在 pom 文件中添加如下部分.(不清楚版本可以在 Maven 仓库中搜索)
- <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <version>1.16.18</version>
- <scope>provided</scope>
- </dependency>
2.idea 插件
3. 注解的说明
@NonNull
or: How I learned to stop worrying and love the NullPointerException.
该注解使用在属性上, 该注解用于属的非空检查, 当放在 setter 方法的字段上, 将生成一个空检查, 如果为空, 则抛出 NullPointerException.
该注解会默认是生成一个无参构造.
- public class User implements Serializable {
- private static final long serialVersionUID = 1L;
- private Integer uid;
- @NonNull
- @Setter
- @Getter
- private String username;
- private boolean flag;
- }
如果测试的时候 username 为空的情况下结果如下:
- Exception in thread "main" java.lang.NullPointerException: username
- at com.taojian.tblog.lombok.User.setUsername(User.java:28)
- at com.taojian.tblog.lombok.Test.main(Test.java:15)
- @Cleanup
- Automatic resource management: Call your close() methods safely with no hassle.
该注解使用在属性前, 该注解是用来保证分配的资源被释放. 在本地变量上使用该注解, 任何后续代码都将封装在 try/finally 中, 确保当前作用于中的资源被释放. 默认 @Cleanup 清理的方法为 close, 可以使用 value 指定不同的方法名称
- import java.io.*;
- public class CleanupExample {
- public static void main(String[] args) throws IOException {
- InputStream in = new FileInputStream(args[0]);
- try {
- OutputStream out = new FileOutputStream(args[1]);
- try {
- byte[] b = new byte[10000];
- while (true) {
- int r = in.read(b);
- if (r == -1) break;
- out.write(b, 0, r);
- }
- } finally {
- if (out != null) {
- out.close();
- }
- }
- } finally {
- if (in != null) {
- in.close();
- }
- }
- }
- }
使用后:
- import lombok.Cleanup;
- import java.io.*;
- public class CleanupExample {
- public static void main(String[] args) throws IOException {
- @Cleanup InputStream in = new FileInputStream(args[0]);
- @Cleanup OutputStream out = new FileOutputStream(args[1]);
- byte[] b = new byte[10000];
- while (true) {
- int r = in.read(b);
- if (r == -1) break;
- out.write(b, 0, r);
- }
- }
- }
- @Getter/@Setter
- Never write public int getFoo() {return foo;} again.
@Getter 就相对于是属性的 get()方法,@Setter 就相当于属性的 set()方法.
The generated getter/setter method will be public unless you explicitly specify an AccessLevel, as shown in the example below. Legal access levels are PUBLIC, PROTECTED, PACKAGE, and PRIVATE.
这句话的意思就是可以指定设置的 getter,setter 的方法的权限, @Setter(AccessLevel.PROTECTED) 这个就表示是一个 protected 属性.
- @Setter(AccessLevel.PROTECTED) private String name;
- /**
- * Changes the name of this person.
- *
- * @param name The new value.
- */
- protected void setName(String name) {
- this.name = name;
- }
使用前:
- public class User implements Serializable {
- private static final long serialVersionUID = 1L;
- private Integer uid;
- private String username;
- private String password;
- public Integer getUid() {
- return uid;
- }
- public String getUsername() {
- return username;
- }
- public String getPassword() {
- return password;
- }
- public void setUid(Integer uid) {
- this.uid = uid;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- }
使用后:
- @Getter
- @Setter
- public class User implements Serializable {
- private static final long serialVersionUID = 1L;
- private Integer uid;
- private String username;
- private String password;
- }
- @ToString
- No need to start a debugger to see your fields: Just let lombok generate a toString for you!
1, 如果需要可以通过注释参数 includeFieldNames 来控制输出中是否包含的属性名称.
2, 可以通过 exclude 参数中包含字段名称, 可以从生成的方法中排除特定字段.
3, 可以通过 callSuper 参数控制父类的输出.
@ToString(exclude="column")
意义: 排除 column 列所对应的元素, 即在生成 toString 方法时不包含 column 参数;
@ToString(exclude={"column1","column2"})
意义: 排除多个 column 列所对应的元素, 其中间用英文状态下的逗号进行分割, 即在生成 toString 方法时不包含多个 column 参数;
@ToString(of="column")
意义: 只生成包含 column 列所对应的元素的参数的 toString 方法, 即在生成 toString 方法时只包含 column 参数;;
@ToString(of={"column1","column2"})
意义: 只生成包含多个 column 列所对应的元素的参数的 toString 方法, 其中间用英文状态下的逗号进行分割, 即在生成 toString 方法时只包含多个 column 参数;
使用前:
- public class User implements Serializable {
- private static final long serialVersionUID = 1L;
- private Integer uid;
- private String username;
- private String password;
- @Override
- public String toString() {
- return super.toString();
- }
- }
使用后:
- @ToString
- public class User implements Serializable {
- private static final long serialVersionUID = 1L;
- private Integer uid;
- private String username;
- private String password;
- @EqualsAndHashCode
Equality made easy: Generates hashCode and equals implementations from the fields of your object..
可以使用 @EqualsAndHashCodelombok 生成 equals(Object other)和 hashCode()方法的实现来注释任何类定义
作用于类, 自动重写类的 equals(),hashCode()方法. 常用的参数有 exclude(指定方法中不包含的属性),callSuper(方法中是否包含父类 ToString()方法返回的值)
使用前:
使用后:
- import lombok.EqualsAndHashCode;
- @EqualsAndHashCode
- public class EqualsAndHashCodeExample {
- private transient int transientVar = 10;
- private String name;
- private double score;
- @EqualsAndHashCode.Exclude private Shape shape = new Square(5, 10);
- private String[] tags;
- @EqualsAndHashCode.Exclude private int id;
- public String getName() {
- return this.name;
- }
- // 因为有继承的关系, 所以要设置 true, 如果没有, 只继承了 Object 类的时候, 就会报错
- @EqualsAndHashCode(callSuper=true)
- public static class Square extends Shape {
- private final int width, height;
- public Square(int width, int height) {
- this.width = width;
- this.height = height;
- }
- }
- }
使用后:
- import java.util.Arrays;
- public class EqualsAndHashCodeExample {
- private transient int transientVar = 10;
- private String name;
- private double score;
- private Shape shape = new Square(5, 10);
- private String[] tags;
- private int id;
- public String getName() {
- return this.name;
- }
- @Override public boolean equals(Object o) {
- if (o == this) return true;
- if (!(o instanceof EqualsAndHashCodeExample)) return false;
- EqualsAndHashCodeExample other = (EqualsAndHashCodeExample) o;
- if (!other.canEqual((Object)this)) return false;
- if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
- if (Double.compare(this.score, other.score) != 0) return false;
- if (!Arrays.deepEquals(this.tags, other.tags)) return false;
- return true;
- }
- @Override public int hashCode() {
- final int PRIME = 59;
- int result = 1;
- final long temp1 = Double.doubleToLongBits(this.score);
- result = (result*PRIME) + (this.name == null ? 43 : this.name.hashCode());
- result = (result*PRIME) + (int)(temp1 ^ (temp1>>> 32));
- result = (result*PRIME) + Arrays.deepHashCode(this.tags);
- return result;
- }
- protected boolean canEqual(Object other) {
- return other instanceof EqualsAndHashCodeExample;
- }
- public static class Square extends Shape {
- private final int width, height;
- public Square(int width, int height) {
- this.width = width;
- this.height = height;
- }
- @Override public boolean equals(Object o) {
- if (o == this) return true;
- if (!(o instanceof Square)) return false;
- Square other = (Square) o;
- if (!other.canEqual((Object)this)) return false;
- if (!super.equals(o)) return false;
- if (this.width != other.width) return false;
- if (this.height != other.height) return false;
- return true;
- }
- @Override public int hashCode() {
- final int PRIME = 59;
- int result = 1;
- result = (result*PRIME) + super.hashCode();
- result = (result*PRIME) + this.width;
- result = (result*PRIME) + this.height;
- return result;
- }
- protected boolean canEqual(Object other) {
- return other instanceof Square;
- }
- }
- }
- @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor
- Constructors made to order: Generates constructors that take no arguments, one argument per final / non-nullfield, or one argument for every field.
@NoArgsConstructor 相对于:
public User(){}
@RequiredArgsConstructor 该注解使用在类上, 使用类中所有带有 @NonNull 注解的或者带有 final 修饰的成员变量生成对应的构造方法.
@NoArgsConstructor 相对于:
- public User(Integer uid, String username, boolean flag) {
- this.uid = uid;
- this.username = username;
- this.flag = flag;
- }
- @Data
- All together now: A shortcut for @ToString, @EqualsAndHashCode, @Getter on all fields, and @Setter on all non-final fields, and @RequiredArgsConstructor!
该注解使用在类上, 该注解是最常用的注解, 它结合了 @ToString,@EqualsAndHashCode, @Getter 和 @Setter. 本质上使用 @Data 注解, 类默认 @ToString 和 @EqualsAndHashCode 以及每个字段都有 @Setter 和 @getter. 该注解也会生成一个公共构造函数, 可以将任何 @NonNull 和 final 字段作为参数.
虽然 @Data 注解非常有用, 但是它没有与其他注解相同的控制粒度.@Data 提供了一个可以生成静态工厂的单一参数, 将 staticConstructor 参数设置为所需要的名称, Lombok 自动生成的构造函数设置为私有, 并提供公开的给定名称的静态工厂方法.
- /**
- * @description:
- * @author: taojian
- * @create: 2018-09-30 22:32
- * 实际上含有这些方法
- * getUid
- * getUsername
- * isFlag 这里是 isFlag(), 而不是 getFlag()
- * setUid
- * setUsername
- * setFlag
- * equals
- * hashCode
- * canEqual
- * toString
- **/
- @Data
- public class User implements Serializable {
- private static final long serialVersionUID = 1L;
- private Integer uid;
- private String username;
- private boolean flag;
- @Data
- public class User implements Serializable {
- private static final long serialVersionUID = 1L;
- private Integer uid;
- private String username;
- private boolean flag;
- }
- @Value
Immutable classes made very easy.
这个注解用在 类 上, 会生成含所有参数的构造方法, get 方法, 此外还提供了 equals,hashCode,toString 方法. 注意: 没有 setter 类似 @Data
- /**
- * @description:
- * @author: taojian
- * @create: 2018-09-30 22:32
- * User
- * getUid
- * getUsername
- * isFlag
- * equals
- * hashCode
- * toString
- * serialVersionUID
- * uid
- * username
- * flag
- **/
- @Value
- public class User implements Serializable {
- private static final long serialVersionUID = 1L;
- private Integer uid;
- private String username;
- private boolean flag;
- }
- @Builder
- ... and Bob's your uncle: No-hassle fancy-pants APIs for object creation!
Project Lombok 的 @Builder 是一种在不编写样板代码的情况下使用 Builder 模式的有用机制. 我们可以将此注释应用于 类 或方法.
在类上使用 @Builder
- /**
- * @description:
- * User
- * getUid
- * getUsername
- * isFlag
- * builder 这个方法是增加的方法
- **/
- @Getter
- @Builder
- public class User implements Serializable {
- private static final long serialVersionUID = 1L;
- private Integer uid;
- private String username;
- private boolean flag;
- }
- public class Test {
- public static void main(String[] args) {
- User user = User.builder().username("taojian").flag(true).uid(1).build();
- System.out.println(user.getUsername().equals("taojian")); // true
- }
- }
2. 在方法上使用 @Builder
假设我们正在使用我们想要使用构建器构造的对象, 但我们无法修改源或扩展类.
首先, 让我们使用 Lombok 的 @Value 注释创建一个快速示例:
- @Value
- final class ImmutableClient {
- private int id;
- private String name;
- }
现在我们有一个带有两个不可变成员的最终 类, 它们的 getter 和一个 all-arguments 构造函数.
我们介绍了如何在 Class 上 使用 @Builder, 但我们也可以在方法上使用它. 我们将使用此功能来解决无法修改或扩展 ImmutableClient 的问题.
接下来, 我们将使用创建 ImmutableClients 的方法创建一个新类:
- class ClientBuilder {
- @Builder(builderMethodName = "builder")
- public static ImmutableClient newClient(int id, String name) {
- return new ImmutableClient(id, name);
- }
- }
这个注解创建了一个名为法生成器 () 是返回一个生成器来创建 ImmutableClients.
现在我们可以构建一个 ImmutableClient:
- ImmutableClient testImmutableClient = ClientBuilder.builder()
- .name("foo")
- .id(1)
- .build();
- assertThat(testImmutableClient.getName())
- .isEqualTo("foo");
- assertThat(testImmutableClient.getId())
- .isEqualTo(1);
- @SneakyThrows
- To boldly throw checked exceptions where no one has thrown them before!
该注解使用在方法上, 这个注解用在 方法 上, 可以将方法中的代码用 try-catch 语句包裹起来, 捕获异常并在 catch 中用 Lombok.sneakyThrow(e) 把异常抛出, 可以使用 @SneakyThrows(Exception.class) 的形式指定抛出哪种异常. 该注解需要谨慎使用
使用前:
- import lombok.Lombok;
- public class SneakyThrowsExample implements Runnable {
- public String utf8ToString(byte[] bytes) {
- try {
- return new String(bytes, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw Lombok.sneakyThrow(e);
- }
- }
- public void run() {
- try {
- throw new Throwable();
- } catch (Throwable t) {
- throw Lombok.sneakyThrow(t);
- }
- }
- }
使用后:
- import lombok.SneakyThrows;
- public class SneakyThrowsExample implements Runnable {
- @SneakyThrows(UnsupportedEncodingException.class)
- public String utf8ToString(byte[] bytes) {
- return new String(bytes, "UTF-8");
- }
- @SneakyThrows
- public void run() {
- throw new Throwable();
- }
- }
- @Synchronized
- synchronized done right: Don't expose your locks.
该注解使用在类或者实例方法上, Synchronized 在一个方法上, 使用关键字可能会导致结果和想要的结果不同, 因为多线程情况下会出现异常情况. Synchronized
关键字将在 this 示例方法情况下锁定当前对象, 或者 class 讲台方法的对象上多锁定. 这可能会导致死锁现象. 一般情况下建议锁定一个专门用于此目的的独立锁, 而不是允许公共对象进行锁定. 该注解也是为了达到该目的.
使用前:
- public class SynchronizedExample {
- private static final Object $LOCK = new Object[0];
- private final Object $lock = new Object[0];
- private final Object readLock = new Object();
- public static void hello() {
- synchronized($LOCK) {
- System.out.println("world");
- }
- }
- public int answerToLife() {
- synchronized($lock) {
- return 42;
- }
- }
- public void foo() {
- synchronized(readLock) {
- System.out.println("bar");
- }
- }
- }
使用后:
- mport lombok.Synchronized;
- public class SynchronizedExample {
- private final Object readLock = new Object();
- @Synchronized
- public static void hello() {
- System.out.println("world");
- }
- @Synchronized
- public int answerToLife() {
- return 42;
- }
- @Synchronized("readLock")
- public void foo() {
- System.out.println("bar");
- }
- }
- @Log @Slf4j
- Captain's Log, stardate 24435.7:"What was that line again?"
日志类型
experimental
Head to the lab: The new stuff we're working on.
- @CommonsLog
- Creates private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
- @Flogger
- Creates private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass();
- @JBossLog
- Creates private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
- @Log
- Creates private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
- @Log4j
- Creates private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
- @Log4j2
- Creates private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
- @Slf4j
- Creates private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
- @XSlf4j
- Creates private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
使用前:
- public class LogExample {
- private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
- public static void main(String... args) {
- log.severe("Something's wrong here");
- }
- }
- public class LogExampleOther {
- private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleOther.class);
- public static void main(String... args) {
- log.error("Something else is wrong here");
- }
- }
- public class LogExampleCategory {
- private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("CounterLog");
- public static void main(String... args) {
- log.error("Calling the'CounterLog'with a message");
- }
- }
使用后:
- import lombok.extern.java.Log;
- import lombok.extern.slf4j.Slf4j;
- @Log
- public class LogExample {
- public static void main(String... args) {
- log.severe("Something's wrong here");
- }
- }
- @Slf4j
- public class LogExampleOther {
- public static void main(String... args) {
- log.error("Something else is wrong here");
- }
- }
- @CommonsLog(topic="CounterLog")
- public class LogExampleCategory {
- public static void main(String... args) {
- log.error("Calling the'CounterLog'with a message");
- }
- }
参考文章链接:
- https://www.baeldung.com/lombok-builder
- https://blog.csdn.net/motui/article/details/79012846
- https://blog.csdn.net/motui/article/details/79012846
- https://projectlombok.org/
- https://segmentfault.com/a/1190000005133786
来源: https://www.cnblogs.com/tojian/p/9822771.html