使用lombok写更简洁的Java代码

一、简介

  在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
@NoArgsConstructor
public 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
@Setter
public 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

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

@NoArgsConstructor
public 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

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

@AllArgsConstructor
public 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(Integer id, Integer sex, String name) {
        this.id = id;
        this.sex = sex;
        this.name = name;
    }
}
@ToString

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

@ToString
public 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方法,如:

@EqualsAndHashCode
public 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属性来控制的,具体可以点进去看看这个属性,可以通过这个属性改变生成的构造器的权限修饰符。

@Builder
public 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修饰
其实就是一个工具类常有的做法。如:

@UtilityClass
public 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依赖。如:

@Log4j
public 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之后,在程序编译期就会为我们生成一样的代码,虽然我们在源文件中看到的没有那些代码,但经过编译后就有了,效果是一样的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值