Java Lombok的介绍和使用方法

一、Lombok是什么

官网介绍如下:

Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.
Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.

Lombok是一个Java类库,它提供了很多注解可以帮我们大大简化冗余代码,提升开发人员的开发效率。比如我们在写JavaBean时要给每个属性添加对应的 getter/setter、toString方法、构造器等一大堆代码,这些代码很冗长也没有什么技术含量,而且修改属性时还要去改对应的方法,浪费时间还容易出错。

Lombok可以通过添加注解的方法,在编译时自动为属性生成getter/setter、toString、构造器等代码,我们在源码中不再修改维护这一堆代码,只需添加注解即可,编译后的class文件中会自动生成。

二、使用方法
1、引入Maven依赖
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.16</version>
    <scope>provided</scope>
</dependency>

scope为provided,表明只在编译阶段生效,不打到包里,因为Lombok是在编译期生效,将带Lombok注解的Java文件编译为完整的Class文件。

2、Idea中安装Lombok插件

打开 File -> Settings -> Plugins,搜索 Lombok,点击 Installed 即可。
在这里插入图片描述

三、常用注解

对常用的注解进行说明,为了直观体现每个注解的效果,会列出注解在源码中的使用方式和编译后class文件中的实际效果

@Setter

注解在类上,为类中所有属性提供Setter方法;注解在某属性上,为该属性提供Setter方法。

源码

@Setter
public class UserInfo01 {

    private String userId;

    @Setter
    private String userName;

    @Setter
    private Integer age;

}

实际效果

public class UserInfo01 {
    
    private String userId;
    
    private String userName;
    
    private Integer age;

    public UserInfo01() {
    }

    public void setUserId(final String userId) {
        this.userId = userId;
    }

    public void setUserName(final String userName) {
        this.userName = userName;
    }

    public void setAge(final Integer age) {
        this.age = age;
    }
    
}
@Getter

注解在类上,为类中所有属性提供Getter方法;注解在某属性上,为该属性提供Getter方法。

源码

@Getter
public class UserInfo02 {

    private String userId;

    @Setter
    private String userName;

    @Setter
    private Integer age;

}
@NoArgsConstructor

注解在类上,为类提供一个无参的构造方法。类中有 final 字段没有被初始化时,编译器会报错,此时可用 @NoArgsConstructor(force = true),然会为没有初始化的 final 字段设置默认值。

源码

@NoArgsConstructor(force = true)
public class UserInfo03 {

    private final String userId;

    private String userName;

    private Integer age;

}

实际效果

public class UserInfo03 {
    
    private final String userId = null;
    
    private String userName;
    
    private Integer age;

    public UserInfo03() {
    }
    
}

@AllArgsConstructor

注解在类上,为类提供一个全参的构造方法。

源码

@AllArgsConstructor
public class UserInfo04 {

    private String userId;

    private String userName;

    private Integer age;

}

实际效果

public class UserInfo04 {
    
    private String userId;
    
    private String userName;
    
    private Integer age;

    public UserInfo04(final String userId, final String userName, final Integer age) {
        this.userId = userId;
        this.userName = userName;
        this.age = age;
    }
    
}
@RequiredArgsConstructor

注解在类上,为未初始化的final属性提供一个private的构造方法;可通过staticName参数生成一个static方法。

源码

@RequiredArgsConstructor(staticName = "of")
public class UserInfo05 {

    private final String userId;

    private final String userName = "张三";

    private Integer age;

}

实际效果

public class UserInfo05 {
    
    private final String userId;
    
    private final String userName = "张三";
    
    private Integer age;

    private UserInfo05(final String userId) {
        this.userId = userId;
    }

    public static UserInfo05 of(final String userId) {
        return new UserInfo05(userId);
    }
    
}
@Builder

注解在类上,建造者模式的一个变种,在创建复杂对象时常使用。

源码

@Builder
public class UserInfo06 {

    private final String userId;

    private final String userName;

    private Integer age;

}

实际效果

public class UserInfo06 {
    
    private final String userId;
    
    private final String userName;
    
    private Integer age;

    UserInfo06(final String userId, final String userName, final Integer age) {
        this.userId = userId;
        this.userName = userName;
        this.age = age;
    }

    public static UserInfo06.UserInfo06Builder builder() {
        return new UserInfo06.UserInfo06Builder();
    }

    public static class UserInfo06Builder {
        
        private String userId;
        
        private String userName;
        
        private Integer age;

        UserInfo06Builder() {
        }

        public UserInfo06.UserInfo06Builder userId(final String userId) {
            this.userId = userId;
            return this;
        }

        public UserInfo06.UserInfo06Builder userName(final String userName) {
            this.userName = userName;
            return this;
        }

        public UserInfo06.UserInfo06Builder age(final Integer age) {
            this.age = age;
            return this;
        }

        public UserInfo06 build() {
            return new UserInfo06(this.userId, this.userName, this.age);
        }

        public String toString() {
            return "UserInfo06.UserInfo06Builder(userId=" + this.userId + ", userName=" + this.userName + ", age=" + this.age + ")";
        }
    }
}

使用Builder模式创建对象

public class BuilderTest {

    public static void main(String[] args) {
        // Builder模式创建对象
        UserInfo06 userInfo06 = UserInfo06.builder().userId("1").userName("张三").age(99).build();
    }

}
@Data

注解在类上,是@Getter、@Setter、@ToString、@EqualsAndHashCode、 @RequiredArgsConstructor的集合。

源码

@Data
public class UserInfo07 {

    private String userId;

    private String userName;

    private Integer age;

}

实际效果

public class UserInfo07 {
    
    private String userId;
    
    private String userName;
    
    private Integer age;

    public UserInfo07() {
    }

    public String getUserId() {
        return this.userId;
    }

    public String getUserName() {
        return this.userName;
    }

    public Integer getAge() {
        return this.age;
    }

    public void setUserId(final String userId) {
        this.userId = userId;
    }

    public void setUserName(final String userName) {
        this.userName = userName;
    }

    public void setAge(final Integer age) {
        this.age = age;
    }

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof UserInfo07)) {
            return false;
        } else {
            UserInfo07 other = (UserInfo07)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label47: {
                    Object this$age = this.getAge();
                    Object other$age = other.getAge();
                    if (this$age == null) {
                        if (other$age == null) {
                            break label47;
                        }
                    } else if (this$age.equals(other$age)) {
                        break label47;
                    }

                    return false;
                }

                Object this$userId = this.getUserId();
                Object other$userId = other.getUserId();
                if (this$userId == null) {
                    if (other$userId != null) {
                        return false;
                    }
                } else if (!this$userId.equals(other$userId)) {
                    return false;
                }

                Object this$userName = this.getUserName();
                Object other$userName = other.getUserName();
                if (this$userName == null) {
                    if (other$userName != null) {
                        return false;
                    }
                } else if (!this$userName.equals(other$userName)) {
                    return false;
                }

                return true;
            }
        }
    }

    protected boolean canEqual(final Object other) {
        return other instanceof UserInfo07;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $age = this.getAge();
        int result = result * 59 + ($age == null ? 43 : $age.hashCode());
        Object $userId = this.getUserId();
        result = result * 59 + ($userId == null ? 43 : $userId.hashCode());
        Object $userName = this.getUserName();
        result = result * 59 + ($userName == null ? 43 : $userName.hashCode());
        return result;
    }

    public String toString() {
        return "UserInfo07(userId=" + this.getUserId() + ", userName=" + this.getUserName() + ", age=" + this.getAge() + ")";
    }
}
@Value

注解在类上,和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,也不会生成set方法。

源码

@Value
public class UserInfo08 {

    private String userId;

    private String userName;

    private Integer age;

}

实际效果

public final class UserInfo08 {
    private final String userId;
    private final String userName;
    private final Integer age;

    public UserInfo08(final String userId, final String userName, final Integer age) {
        this.userId = userId;
        this.userName = userName;
        this.age = age;
    }

    public String getUserId() {
        return this.userId;
    }

    public String getUserName() {
        return this.userName;
    }

    public Integer getAge() {
        return this.age;
    }

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof UserInfo08)) {
            return false;
        } else {
            UserInfo08 other;
            label44: {
                other = (UserInfo08)o;
                Object this$age = this.getAge();
                Object other$age = other.getAge();
                if (this$age == null) {
                    if (other$age == null) {
                        break label44;
                    }
                } else if (this$age.equals(other$age)) {
                    break label44;
                }

                return false;
            }

            Object this$userId = this.getUserId();
            Object other$userId = other.getUserId();
            if (this$userId == null) {
                if (other$userId != null) {
                    return false;
                }
            } else if (!this$userId.equals(other$userId)) {
                return false;
            }

            Object this$userName = this.getUserName();
            Object other$userName = other.getUserName();
            if (this$userName == null) {
                if (other$userName != null) {
                    return false;
                }
            } else if (!this$userName.equals(other$userName)) {
                return false;
            }

            return true;
        }
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $age = this.getAge();
        int result = result * 59 + ($age == null ? 43 : $age.hashCode());
        Object $userId = this.getUserId();
        result = result * 59 + ($userId == null ? 43 : $userId.hashCode());
        Object $userName = this.getUserName();
        result = result * 59 + ($userName == null ? 43 : $userName.hashCode());
        return result;
    }

    public String toString() {
        return "UserInfo08(userId=" + this.getUserId() + ", userName=" + this.getUserName() + ", age=" + this.getAge() + ")";
    }
}
@Slf4j

注解在类上;为类提供一个 属性名为 log 的日志对象。

源码

@Slf4j
public class Slf4jTest {

    public static void main(String[] args) {
        log.info("日志打印测试");
    }

}

实际效果

public class Slf4jTest {
    
    private static final Logger log = LoggerFactory.getLogger(Slf4jTest.class);

    public Slf4jTest() {
    }

    public static void main(String[] args) {
        log.info("日志打印测试");
    }
    
}
@Cleanup

注解在流上,生成关闭流的方法。

源码

public class CleanupTest {

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

}

实际效果

public class CleanupTest {
    
    public CleanupTest() {
    }

    public static void main(String[] args) throws IOException {
        FileInputStream in = new FileInputStream(args[0]);
        try {
            FileOutputStream out = new FileOutputStream(args[1]);
            try {
                byte[] b = new byte[10000];
                while(true) {
                    int r = in.read(b);
                    if (r == -1) {
                        return;
                    }
                    out.write(b, 0, r);
                }
            } finally {
                if (Collections.singletonList(out).get(0) != null) {
                    out.close();
                }
            }
        } finally {
            if (Collections.singletonList(in).get(0) != null) {
                in.close();
            }
        }
    }
    
}

@SneakyThrows

注解在方法上,给方法中的代码添加try/catch捕获异常。

源码

public class SneakyThrowsTest {

    @SneakyThrows
    public void test() {
        System.out.println("test");
    }

}

实际效果

public class SneakyThrowsTest {
    
    public SneakyThrowsTest() {
    }

    public void test() {
        try {
            System.out.println("test");
        } catch (Throwable var2) {
            throw var2;
        }
    }
    
}
@Synchronized

注解在方法上,给方法中的代码添加同步锁。

源码

public class SynchronizedTest {

    @Synchronized
    public void test() {
        System.out.println("test");
    }

}

实际效果

public class SynchronizedTest {
    
    private final Object $lock = new Object[0];

    public SynchronizedTest() {
    }

    public void test() {
        synchronized(this.$lock) {
            System.out.println("test");
        }
    }
    
}
@NonNull

注解在参数上,在方法或构造函数的参数上使用@NonNull会给参数生成null-check语句。

public class NonNullTest {

    public static void main(String[] args) {
        test(null);
    }

    public static void test(@NonNull String id) {
        System.out.println(id);
    }

}

实际效果

public class NonNullTest {
    
    public NonNullTest() {
    }

    public static void main(String[] args) {
        test((String) null);
    }

    public static void test(@NonNull String id) {
        if (id == null) {
            throw new NullPointerException("id is marked non-null but is null");
        } else {
            System.out.println(id);
        }
    }
    
}
四、Lombok的优点和缺点

Lombok当然不是万能的,使用Lombok能给开发人员提供很大的便利,同时也会带来一些问题,其优缺点如下。

优点:

  • 简化了大量的冗余代码,注解代替getter/setter等方法,能让源码更简洁;
  • 减少了代码维护 难度,修改属性后,上述方法也会随之改变,防止忘改错该问题;
  • 提升了开发效率,减少重复劳动。

缺点:

  • 使用Lombok需要在Idea中安装插件,团队里一个人用了Lombok其它人也得跟着用;
  • Lombok很多方法是自动生成的,屏蔽了代码的内部逻辑,一定程度上降低了代码的可读性;
  • 对Lombok理解较少的话会出现意想不到的现象,比如使用@Data注解时, 会自动生成equals()方法,但是这个equals()方法只会比较子类的属性,不会考虑从父类继承的属性,要想比较父类方法需添加@EqualsAndHashCode(callSuper=true)注解。

Lombok有优点也有缺点,个人认为瑕不掩瑜,还是比较好用的,大家根据自己情况按需使用。

五、参考文档

官网地址

https://projectlombok.org/features/all

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值