首頁 > Java > java教程 > Java庫lombok及註解如何使用

Java庫lombok及註解如何使用

王林
發布: 2023-06-03 21:28:14
轉載
718 人瀏覽過

Lombok是什么

Lombok是一个旨在减少代码开发工作的Java库。它提供了一些简单的注解,并以此来消除java中臃肿的模版代码,比如 pojo 中最常见的 setter/getter 方法, 比如 toString 方法, 比如 equals 方法等等,还可以帮助我们关闭流,即使 JDK7 中已经有了 TWR 特性,但这个包很值得一试。

通过几个简单的注解,将模版代码在编译时写入程序。在 Eclipse 中,生成的方法可以在 Outline 窗口中查看,但在源代码中是没有痕迹的

安装

首先去 lombok 官网下载jar 包。

只是把 jar 包下载下来并导入工程中,会发现 IDE 不识别它的注解,那怎么办?

对于eclipse

将 lombok.jar 复制到 eclipse.ini 所在的目录下,然后编辑 eclipse.ini 文件, 在它的末尾插入以下两行并保存:

1

2

Xbootclasspath/a:lombok.jar

javaagent:lombok.jar

登入後複製

接着重启 eclipse 就可以愉快地使用这个库了。

对于 IDEA

在 IntelliJ 的插件中心可以找到它。

QuickStart

Lombok 提供的注解不多,但都好用,简要说一下常用的几个。

@Setter/@Getter

这两个注解修饰成员变量,可用于生成 setter/gettter 模版代码。
举个栗子:

1

2

3

4

5

6

7

8

import lombok.AccessLevel;

import lombok.Getter;

import lombok.Setter;

public class Student {

    @Setter @Getter private String name;

    @Getter(AccessLevel.PROTECTED) private int age;// 可以指定访问权限

    @Setter @Getter private String[] hobbies;

}

登入後複製

将字节码文件反编译后可以看到下面这段代码

1

2

3

4

5

6

7

8

9

10

public class Student {

  private String name;

  private int age;

  private String[] hobbies;

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

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

  protected int getAge() { return this.age; }

  public String[] getHobbies() { return this.hobbies; }

  public void setHobbies(String[] hobbies) { this.hobbies = hobbies; }

}

登入後複製

@ToString

1

2

3

4

5

6

7

import lombok.ToString;

@ToString(exclude="id")

public class ToStringExample {

    private int id;

    private String name;

    private String[] tags;

}

登入後複製

编译后

1

2

3

4

5

6

7

8

9

import java.util.Arrays;

public class ToStringExample {

  public String toString() {

    return "ToStringExample(name=" + this.name + ", tags=" + Arrays.deepToString(this.tags) + ")";

  }

  private int id;

  private String name;

  private String[] tags;

}

登入後複製

我们发现,对于数组,在写 toString 方法时使用了 Arrays类的 静态方法 deepToString

来看 eclipse 自动生成的 toString 方法:

1

2

3

4

@Override

public String toString() {

    return "ToStringExample [name=" + name + ", tags=" + Arrays.toString(tags) + "]";

}

登入後複製

eclipse 中对于数组采用的是 Arrays.toString()

区别:这两个方法的区别是这样的,对于多维数组,使用 toString 只能打印出内部数组的名字,这时需要使用 deepToString 方法,它能将内部数组的内容全部打印出来。

exclude 参数

可以指定哪些属性不出现在 toString 方法中, 比如 exclude={"id", "name"}

doNotUseGetters 参数

当类中有成员变量的 getter 方法时,生成 toString 方法会使用这些 getter 方法,比如

1

2

3

public String toString() {

    return "ToStringExample(name=" + getName() + ", tags=" + Arrays.deepToString(getTags()) + ")";

}

登入後複製

但是将该参数设置为 true 时(默认为 false),生成 toString 方法时就不会使用 getter 方法,而是直接使用这些成员变量,比如

1

2

3

public String toString() {

    return "ToStringExample(name=" + this.name + ", tags=" + Arrays.deepToString(this.tags) + ")";

}

登入後複製

includeFieldNames参数

原本是以 fieldName = fieldValue 的格式来生成 toString 方法的,但是将该参数设置为 false 后(默认是 true),就不会显示 fieldName 了,而只是生成 fieldValue, 比如

1

2

3

public String toString() {

  return "ToStringExample(" + getId() + ", " + getName() + ", " + Arrays.deepToString(getTags()) + ")";

}

登入後複製

callSuper 参数

若类 A 是类 B 的子类,那么在 A 类重写 toString 时,若把该参数设置为 true,会加入下面这段代码,即也会把父类 B 的 toString 也写入。

1

super=" + super.toString()

登入後複製

@NonNull

检查传入对象是否为 Null,若为null,则抛出NullPointerException异常。
举个栗子

1

2

3

4

5

6

7

import lombok.NonNull;

public class NonNullExample extends Student{

    private String name;

    public NonNullExample(@NonNull Student student) {

        this.name = student.getName();

    }

}

登入後複製

编译后代码

1

2

3

4

5

6

7

8

9

import lombok.NonNull;

public class NonNullExample extends Student {

    private String name;

    public NonNullExample(@NonNull Student student) {

        if (student == null)

            throw new NullPointerException("student");

        this.name = student.getName();

  }

}

登入後複製

@EqualsAndHashCode

用在类上,用于生成 equalshashcode 方法。
举个栗子

1

2

3

4

5

6

7

8

@EqualsAndHashCode(exclude={"id"})

public class EqualsAndHashCodeExample {

     private transient int transientVar = 10;

     private String name;

     private double score;

     private String[] tags;

     private int id;

}

登入後複製

编译后代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

import java.util.Arrays;

public class EqualsAndHashCodeExample {

    public int hashCode() {

        int PRIME = 59;

        int result = 1;

        Object $name = this.name;

        result = result * 59 + ($name == null ? 43 : $name.hashCode());

        long $score = Double.doubleToLongBits(this.score);

        result = result * 59 + (int)($score ^ $score >>> 32);

        result = result * 59 + Arrays.deepHashCode(this.tags);

        return result;

    }

    protected boolean canEqual(Object other) {

        return other instanceof EqualsAndHashCodeExample;

    }

    public boolean equals(Object o) {

        if (o == this)  return true;

        if (!(o instanceof EqualsAndHashCodeExample)) return false;

        EqualsAndHashCodeExample other = (EqualsAndHashCodeExample)o;

        if (!other.canEqual(this)) return false;

        Object this$name = this.name;

        Object other$name = other.name;

        if (this$name == null ? other$name != null : !this$name.equals(other$name))

            return false;

        if (Double.compare(this.score, other.score) != 0)

            return false;

        return Arrays.deepEquals(this.tags, other.tags);

    }

private transient int transientVar = 10;

private String name;

private double score;

private String[] tags;

private int id;

}

登入後複製

可以看出transient修饰的变量,不会参与。

参数

参数 of 用来指定参与的变量,其他的跟 @ToString 注解类似。

@Data

该注解用于修饰类,会自动生成getter/setter方法, 以及重写equals(), hashcode()toString()方法。

@Cleanup

该注解可以用来自动管理资源,用在局部变量之前,在当前变量范围内即将执行完毕退出之前会自动清理资源, 自动生成try­finally这样的代码来关闭流

举个栗子:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

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);

       }

     }

}

登入後複製

@NoArgsConstructor/@RequiredArgsConstructor/@AllArgsConstructor

这三个注解修饰在类上。

@NoArgsConstructor 用于生成一个无参构造方法。

@RequiredArgsConstructor 会生成一个包含了被@NotNull标识的变量的构造方法。同样可以设置生成构造方法的权限,使用 access参数进行设置。

@AllArgsConstructor 会生成一个包含所有变量, 同时如果变量使用了@NotNull,会进行是否为空的校验。

举个栗子:

1

2

3

4

5

6

7

8

9

10

11

12

import lombok.*;

@RequiredArgsConstructor(staticName = "of")

@AllArgsConstructor(access = AccessLevel.PROTECTED)

public class ConstructorExample {

    private int x;

    private int y;

    @NonNull private String desc;

    @NoArgsConstructor

    public class NoArgsExample{

        private String field;

    }

}

登入後複製

这与下面这段代码是等价的,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

import java.beans.ConstructorProperties;

public class ConstructorExample {

    public static ConstructorExample of(@lombok.NonNull String desc) {

        return new ConstructorExample(desc);

    }

    private ConstructorExample(@lombok.NonNull String desc) {

        if (desc == null) throw new NullPointerException("desc");

        this.desc = desc;

    }

    @ConstructorProperties({"x", "y", "desc"})

    protected ConstructorExample(int x, int y, @lombok.NonNull String desc) {

        if (desc == null) throw new NullPointerException("desc");

        this.x = x;

        this.y = y;

        this.desc = desc;

    }

    private int x;

    private int y;

    @lombok.NonNull

    private String desc;

    public class NoArgsExample

    {

        private String field;

        public NoArgsExample() {}

    }

}

登入後複製

@Value

该注解用于修饰类,是@Data的不可变形式, 相当于为成员变量添加final声明, 只提供getter方法, 而不提供setter方法,然后还有 equals/hashCode/toString方法,以及一个包含所有参数的构造方法。

@builder

用在类、构造器、方法上,为你提供复杂的builder APIs,让你可以像如下方式调用

1

2

Person.builder().name("A

dam Savage").city("San Francisco").job("Mythbusters").job("Unchained Reaction").build()

登入後複製

举个栗子:

1

2

3

4

5

6

7

import lombok.Builder;

import java.util.Set;

@Builder

public class BuilderExample {

    private String name;

    private int age;

}

登入後複製

反编译代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

package tutorial.lombok;

    public class BuilderExample

    {

        public static class BuilderExampleBuilder

        {

            private String name;

            private int age;

            public BuilderExampleBuilder name(String name)

            {

                this.name = name;

                return this;

            }

            public BuilderExampleBuilder age(int age)

            {

                this.age = age;

                return this;

            }

            public BuilderExample build()

            {

                return new BuilderExample(name, age);

            }

            public String toString()

            {

                return (new StringBuilder()).append("BuilderExample.BuilderExampleBuilder(name=").append(name).append(", age=").append(age).append(")").toString();

            }

            BuilderExampleBuilder()

            {

            }

        }

        private String name;

        private int age;

        BuilderExample(String name, int age)

        {

            this.name = name;

            this.age = age;

        }

        public static BuilderExampleBuilder builder()

        {

            return new BuilderExampleBuilder();

        }

    }

登入後複製

注意:

使用@Singular注解的集合属性名必须使用s结尾, lombok会将属性名结尾的s去掉,剩余的名字会作为方法名, 向这个集合中添加元素。

@Builder 的参数builderClassName设置生成的builder方法名,buildMethodName 设置build方法名,builderMethodName设置builderMethod`方法名。
比如

1

@Builder(builderClassName = "GBuilder", buildMethodName = "buildG", builderMethodName = "GBuilder"

登入後複製

@SneakyThrows

自动抛受检异常, 而无需显式在方法上使用throws语句。

@Synchronized

用在方法上,将方法声明为同步的,并自动加锁,而锁对象是一个私有的属性 LOCK,而java中的synchronized关键字锁对象是this,锁在this或者自己的类对象上存在副作用,就是你不能阻止非受控代码去锁this或者类对象,这可能会导致竞争条件或者其它线程错误。

举个栗子:

1

2

3

4

5

6

7

8

9

10

11

12

import lombok. Synchronized;

public class SynchronizedExample {

    private final Object readLock = new Object() ;

    @Synchronized

    public static void hello() {

        System. out. println("world") ;

    }

    @Synchronized("readLock")

    public void foo() {

        System. out. println("bar") ;

    }

}

登入後複製

反编译代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

public class SynchronizedExample {

    private static 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") ;

        }

    }

}

登入後複製

@Getter(lazy=true)

可以替代经典的Double Check Lock样板代码。

举个栗子:

1

2

3

4

5

6

7

8

9

10

11

import lombok.Getter;

public class GetterLazyExample {

    @Getter(lazy=true) private final double[] cached = expensive();

    private double[] expensive() {

        double[] result = new double[1000000];

        for (int i = 0; i < result.length; i++) {

            result[i] = Math.asin(i);

        }

        return result;

    }

}

登入後複製

反编译代码如下,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

import java.util.concurrent.atomic.AtomicReference;

public class GetterLazyExample

{

    private final AtomicReference cached = new AtomicReference();

    public GetterLazyExample()

    {

    }

    private double[] expensive()

    {

            double result[] = new double[0xf4240];

        for (int i = 0; i < result.length; i++)

            result[i] = Math.asin(i);

        return result;

    }

    public double[] getCached()

    {

        Object value = cached.get();

        if (value == null)

            synchronized (cached)

            {

                value = cached.get();

                if (value == null)

                {

                    double actualValue[] = expensive();

                    value = actualValue != null ? ((Object) (actualValue)) : ((Object) (cached));

                    cached.set(value);

                }

            }

        return (double[])(double[])(value != cached ? value : null);

    }

}

登入後複製

@Log

根据不同的注解生成不同类型的log对象, 但是实例名称都是log, 有六种可选实现类

1

2

3

4

5

6

7

8

9

10

11

12

@CommonsLog

Creates log = org. apache. commons. logging. LogFactory. getLog(LogExample. class) ;

@Log

Creates log = java. util. logging. Logger. getLogger(LogExample. class. getName() ) ;

@Log4j

Creates log = org. apache. log4j. Logger. getLogger(LogExample. class) ;

@Log4j2

Creates log = org. apache. logging. log4j. LogManager. getLogger(LogExample. class) ;

@Slf4j

Creates log = org. slf4j. LoggerFactory. getLogger(LogExample. class) ;

@XSlf4j

Creates log = org. slf4j. ext. XLoggerFactory. getXLogger(LogExample. class) ;

登入後複製

举个栗子,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

import lombok.extern.java.Log;

import lombok.extern.slf4j.Slf4j;

@Log

public class LogExample {

    public static void main(String... args) {

        log.error("Something&#39;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 &#39;CounterLog&#39; with a message");

    }

}

登入後複製

1

@CommonsLog(topic="CounterLog")

登入後複製

这条语句会翻译成这样

1

private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("CounterLog");

登入後複製

以上是Java庫lombok及註解如何使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
java可以做為web的後端嗎?
來自於 1970-01-01 08:00:00
0
0
0
安裝JAVA
來自於 1970-01-01 08:00:00
0
0
0
無法安裝java
來自於 1970-01-01 08:00:00
0
0
0
求救:JAVA加密的資料PHP解密
來自於 1970-01-01 08:00:00
0
0
0
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板