使用lombok写更简洁的Java代码

来源:互联网 发布:java函数调用关系图 编辑:程序博客网 时间:2024/05/21 10:50

一、简介

  在Java开发中,我们经常需要写一些Bean类,这些的结构基本相同,一堆成员变量,一个无参构造器,一堆getter和setter。虽然可以使用IDE的快捷键帮助我们生成getter和setter方法,但是当一个类的字段过多的时候,那些getter/setter、各种构造器、hashCode()还有equals()等一大堆,难道不会让代码很难看吗?

  在这样的环境下lombok应运而生,lombok提供一组注解和IDE(eclipse和IDEA)的插件,帮助我们在编译期完成包括但不限于上述的代码的工具。这些注解都是编译期有效的,所有工作在编译期完成,也就是说,在编写Java Bean的时候给它加上lombok的注解,最终得到的class文件和我们直接写的其实是没有区别的。

二、安装插件

  要使用lombok必先要在集成开发环境中安装插件:

  • 在eclipse中安装

  到https://projectlombok.org/download下载jar,到下载的目录打开命令行,敲入

java -jar lombok.jar

  然后就会跳出lombok的安装程序,按照提示选择eclipse的安装目录,等待安装完即可。如下图所示:(因为我的机子既有eclipse也有myEclipse,所以这里显示了两个目录,选择自己要安装的就行了)
这里写图片描述

小技巧:在windows的资源管理器中按住shift+鼠标右键可以在当前目录打开命令行。

快速打开当前目录下的命令行

  • 在IDEA中安装

  在IDEA中安装插件都是比较容易的:File -> Setting -> Plugins,然后输入lombok搜索插件,然后点击右边的install,这里我已经安装好了,所以就显示了uninstall
搜索lombok

三、如何使用

  安装了插件之后,自己的项目中添加lombok的maven依赖,或者加入lombok的jar包到项目中(但现在谁还会直接使用jar而不用maven呢?)

<dependency>    <groupId>org.projectlombok</groupId>    <artifactId>lombok</artifactId>    <version>1.16.18</version>    <scope>provided</scope></dependency>

现在可以在项目中享受lombok带来的便利了。先看一个例子:

@Getter@Setter@ToString@AllArgsConstructor@NoArgsConstructorpublic class Student {    private Integer id;    private Integer sex;    private String name;}
public static void main(String[] args) {    Student student = new Student();    student.setName("jim");    System.out.println(student);}

控制台打印结果为:

Student(id=null, sex=null, name=jim)

神奇吧~

四,相关API介绍

lombok能够使用的注解都在lombok包下面,以下挑一些常用的讲解,也可以直接看源码,看注释就知道这个注解有什么作用
这里写图片描述

在lombok.experimental包下面也有提供更多的注解,这些都属于实验阶段,也可以使用,但是不保证今后会不支持。
这里写图片描述


@Getter、@Setter

这两个注解可以使用在字段或者类上面,当使用在字段上面,为当前字段生成getter/setter,当使用在类上面的时候为该类所有字段生成getter/setter,如:

@Getter@Setterpublic class Student {    private Integer id;    private Integer sex;    private String name;}

生成的class文件:

public class Student {    private Integer id;    private Integer sex;    private String name;    public Student() {    }    public Integer getId() {        return this.id;    }    public Integer getSex() {        return this.sex;    }    public String getName() {        return this.name;    }    public void setId(Integer id) {        this.id = id;    }    public void setSex(Integer sex) {        this.sex = sex;    }    public void setName(String name) {        this.name = name;    }}

@NoArgsConstructor

使用在类上面,为该类生成一个无参构造器,如:

@NoArgsConstructorpublic class Student {    private Integer id;    private Integer sex;    private String name;}

则生成class为:

public class Student {    private Integer id;    private Integer sex;    private String name;    public Student() {    }}

@AllArgsConstructor

为该类生成全部参数的构造器,如:

@AllArgsConstructorpublic class Student {    private Integer id;    private Integer sex;    private String name;}

则生成:

public class Student {    private Integer id;    private Integer sex;    private String name;    @ConstructorProperties({"id", "sex", "name"})    public Student(Integer id, Integer sex, String name) {        this.id = id;        this.sex = sex;        this.name = name;    }}

@ToString

@ToString也是使用在类上面,为该类的所有字段生成toString方法,跟直接在Eclipse中生成的是一样的,如:

@ToStringpublic class Student {    private Integer id;    private Integer sex;    private String name;}

生成:

public class Student {    private Integer id;    private Integer sex;    private String name;    public Student() {    }    public String toString() {        return "Student(id=" + this.id + ", sex=" + this.sex + ", name=" + this.name + ")";    }}

@EqualsAndHashCode

注解在类上面,为该类生成equals和hashCode方法,如:

@EqualsAndHashCodepublic class Student {    private Integer id;    private Integer sex;    private String name;}

则该类生成:

public class Student {    private Integer id;    private Integer sex;    private String name;    public Student() {    }    public boolean equals(Object o) {        if (o == this) {            return true;        } else if (!(o instanceof Student)) {            return false;        } else {            Student other = (Student)o;            if (!other.canEqual(this)) {                return false;            } else {                label47: {                    Object this$id = this.id;                    Object other$id = other.id;                    if (this$id == null) {                        if (other$id == null) {                            break label47;                        }                    } else if (this$id.equals(other$id)) {                        break label47;                    }                    return false;                }                Object this$sex = this.sex;                Object other$sex = other.sex;                if (this$sex == null) {                    if (other$sex != null) {                        return false;                    }                } else if (!this$sex.equals(other$sex)) {                    return false;                }                Object this$name = this.name;                Object other$name = other.name;                if (this$name == null) {                    if (other$name != null) {                        return false;                    }                } else if (!this$name.equals(other$name)) {                    return false;                }                return true;            }        }    }    protected boolean canEqual(Object other) {        return other instanceof Student;    }    public int hashCode() {        int PRIME = true;        int result = 1;        Object $id = this.id;        int result = result * 59 + ($id == null ? 43 : $id.hashCode());        Object $sex = this.sex;        result = result * 59 + ($sex == null ? 43 : $sex.hashCode());        Object $name = this.name;        result = result * 59 + ($name == null ? 43 : $name.hashCode());        return result;    }}

@Data

@Data是@Getter、@Setter、@ToString和@EqualsAndHashCode等的大合集,直接使用一个@Data注解,等同于使用后者全部,如下例子:

public class Student {    private Integer id;    private Integer sex;    private String name;    public Student() {    }    public Integer getId() {        return this.id;    }    public Integer getSex() {        return this.sex;    }    public String getName() {        return this.name;    }    public void setId(Integer id) {        this.id = id;    }    public void setSex(Integer sex) {        this.sex = sex;    }    public void setName(String name) {        this.name = name;    }    public boolean equals(Object o) {        if (o == this) {            return true;        } else if (!(o instanceof Student)) {            return false;        } else {            Student other = (Student)o;            if (!other.canEqual(this)) {                return false;            } else {                label47: {                    Object this$id = this.getId();                    Object other$id = other.getId();                    if (this$id == null) {                        if (other$id == null) {                            break label47;                        }                    } else if (this$id.equals(other$id)) {                        break label47;                    }                    return false;                }                Object this$sex = this.getSex();                Object other$sex = other.getSex();                if (this$sex == null) {                    if (other$sex != null) {                        return false;                    }                } else if (!this$sex.equals(other$sex)) {                    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(Object other) {        return other instanceof Student;    }    public int hashCode() {        int PRIME = true;        int result = 1;        Object $id = this.getId();        int result = result * 59 + ($id == null ? 43 : $id.hashCode());        Object $sex = this.getSex();        result = result * 59 + ($sex == null ? 43 : $sex.hashCode());        Object $name = this.getName();        result = result * 59 + ($name == null ? 43 : $name.hashCode());        return result;    }    public String toString() {        return "Student(id=" + this.getId() + ", sex=" + this.getSex() + ", name=" + this.getName() + ")";    }}

@Builder

@Builder是构建者模式,使用在类上,可以为该类生成一个内部Builder类,可以使用该Builder类来生成一个实际的类,如下代码所示。
这里注意到,使用@Builder时候会生成一个全部参数的构造器,默认是default权限的,请注意,@Builder是不能和@NoArgsConstructor同时使用的。另外,如果@Builder和@AllArgsConstructor同时使用,生成的全参构造器的权限是public的,这是由@AllArgsConstructor和access属性来控制的,具体可以点进去看看这个属性,可以通过这个属性改变生成的构造器的权限修饰符。

@Builderpublic class Student {    private Integer id;    private Integer sex;    private String name;}
public class Student {    private Integer id;    private Integer sex;    private String name;    @ConstructorProperties({"id", "sex", "name"})    Student(Integer id, Integer sex, String name) {        this.id = id;        this.sex = sex;        this.name = name;    }    public static Student.StudentBuilder builder() {        return new Student.StudentBuilder();    }    public static class StudentBuilder {        private Integer id;        private Integer sex;        private String name;        StudentBuilder() {        }        public Student.StudentBuilder id(Integer id) {            this.id = id;            return this;        }        public Student.StudentBuilder sex(Integer sex) {            this.sex = sex;            return this;        }        public Student.StudentBuilder name(String name) {            this.name = name;            return this;        }        public Student build() {            return new Student(this.id, this.sex, this.name);        }        public String toString() {            return "Student.StudentBuilder(id=" + this.id + ", sex=" + this.sex + ", name=" + this.name + ")";        }    }}

lombok.experimental包

@UtilityClass

该注解使用在类上,使用这个注解后,这个类会
1,最终类,final修饰
2,不能定义构造器,会提供一个private的构造器
3,该类所有方法、字段和内部类都会加上static修饰
其实就是一个工具类常有的做法
如:

@UtilityClasspublic class DBUtils {    private Connection connection;    public Connection getConnection() {        return connection;    }}

则生成:

public final class DBUtils {    private static Connection connection;    public static Connection getConnection() {        return connection;    }    private DBUtils() {        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");    }}

@FieldDefaults

@FieldDefaults使用在类上面,指定该类的字段的权限修饰符,使用这个注解会为该类所有没指明权限修饰符的字段生成修饰符,如下代码。
这里id字段我指明为public最终生成的class中也是public,sex和name字段没有指明修饰符,则按照@FieldDefaults中的level属性,设置修饰符为private

@FieldDefaults(level = AccessLevel.PRIVATE)public class Student {    public Integer id;    Integer sex;    String name;}
public class Student {    public Integer id;    private Integer sex;    private String name;    public Student() {    }}

日志相关的注解

@CommonsLog、@Log 、@JBossLog、@Log4j、@Log4j2、@Slf4j、@XSl4j

  这些都是使用在类上面,为该类生成一个private staitc fianl的名字为log的日志成员变量,唯一的区别就是使用的日志类不同。需要注意的是,在使用这些注解的项目中要添加相应的maven依赖。如:

@Log4jpublic class LogExample {    public void userLog() {        log.info("使用生成的log对象");    }}

编译后:

import org.apache.log4j.Logger;public class LogExample {    private static final Logger log = Logger.getLogger(LogExample.class);    public LogExample() {    }    public void userLog() {        log.info("使用生成的log对象");    }}

其他的类似,都会生成相应的log对象

  • @CommonsLog
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
  • @Log
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
  • @JBossLog
private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
  • @Log4j
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
  • @Log4j2
private static final org.apache.logging.log4j.Logger log = rg.apache.logging.log4j.LogManager.getLogger(LogExample.class);
  • @Slf4j
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
  • @XSl4j
private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);

五、总结

  是不是感觉上面都是贴代码,一大堆繁杂的代码??那就对了,对比一下使用lombok和不使用lombok,代码量差距不要太大。实际开发中,有时候一个bean光是字段就有几十个,要是还写一大堆的Getter和Setter,构造器什么的,这代码,简直不敢看。而使用了lombok之后,在程序编译期就会为我们生成一样的代码,虽然我们在源文件中看到的没有那些代码,但经过编译后就有了,效果是一样的。