Lombok-入门篇

随着编程以及各种框架的发展,大大提供了开发的简洁和便利性。在开发过程中,我们经常要定义各种Bean,在Bean中会出现大量的getter、setter方法,有时还会重写toString等方法,比如:

/**
 * @author javaerui
 * @Description:
 * @date 2021/1/22
 */
public class User {

    public User() {
    }

    public User(String name, long id, Integer age, boolean vip, Boolean svip) {
        this.name = name;
        this.id = id;
        this.age = age;
        this.vip = vip;
        this.svip = svip;
    }

    private String name;

    private long id;

    private Integer age;

    private boolean vip;

    private Boolean svip;

    public String getName() {
        return name;
    }

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

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public Integer getAge() {
        return age;
    }

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

    public boolean isVip() {
        return vip;
    }

    public void setVip(boolean vip) {
        this.vip = vip;
    }

    public Boolean getSvip() {
        return svip;
    }

    public void setSvip(Boolean svip) {
        this.svip = svip;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", age=" + age +
                ", vip=" + vip +
                ", svip=" + svip +
                '}';
    }
}

大量的方法重置着整个类,让这个类看上去失去了很多美观性。于是,Lombok诞生了,我们只需要编写Bean的属性,然后使用Lombok提供的注解便能够完成getter、setter等方法的添加。对于JVM来说,它是只能够识别class字节码的,而我们程序员一般编写的java源码需要先编译成class字节码才能够被JVM识别并运行,所以Lombok是对class字节码做了文章,在.java文件的源码级别使用Lombok提供的注解,Lombok会在类编译成.class字节码的时候根据特定注解对类添加特定的方法,比如:

/**
 * @author javaerui
 * @Description:
 * @date 2021/1/22
 */
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
public class User {

    private String name;

    private long id;

    private Integer age;

    private boolean vip;

    private Boolean svip;

}

编译User.java后,用IDEA打开编译生成的User.class内容:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

public class User {
    private String name;
    private long id;
    private Integer age;
    private boolean vip;
    private Boolean svip;

    public User() {
    }

    public User(String name, long id, Integer age, boolean vip, Boolean svip) {
        this.name = name;
        this.id = id;
        this.age = age;
        this.vip = vip;
        this.svip = svip;
    }

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

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

    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }

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

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

    public boolean isVip() {
        return this.vip;
    }

    public void setVip(boolean vip) {
        this.vip = vip;
    }

    public Boolean getSvip() {
        return this.svip;
    }

    public void setSvip(Boolean svip) {
        this.svip = svip;
    }

    public String toString() {
        return "User{name='" + this.name + '\'' + ", id=" + this.id + ", age=" + this.age + ", vip=" + this.vip + ", svip=" + this.svip + '}';
    }
}

对User类使用了Lombok提供的注解后,类的内容实质上和上面没有使用Lombok的效果是一样的。从源码层对比两个类,使用Lombok注解后,看上去更加简洁明了了。


█ 简单使用

(1)IDEA安装Lombok插件:

(2)引入依赖:

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

(3)以User类为例,查看Lombok提供的注解所对应的方法。

public class User {

    private String name;

    private long id;

    private Integer age;

    private boolean vip;

    private Boolean svip;

}
  • @Getter

对Bean的属性构建标准getter方法。

源码:

@Getter
public class User {

    private String name;

    private long id;

    private Integer age;

    private boolean vip;

    private Boolean svip;

}

编译后:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

public class User {
    private String name;
    private long id;
    private Integer age;
    private boolean vip;
    private Boolean svip;

    public User() {
    }

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

    public long getId() {
        return this.id;
    }

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

    public boolean isVip() {
        return this.vip;
    }

    public Boolean getSvip() {
        return this.svip;
    }
}
  • @Setter

对属性构建set方法。

源码:

@Setter
public class User {

    private String name;

    private long id;

    private Integer age;

    private boolean vip;

    private Boolean svip;

}

编译后:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

public class User {
    private String name;
    private long id;
    private Integer age;
    private boolean vip;
    private Boolean svip;

    public User() {
    }

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

    public void setId(long id) {
        this.id = id;
    }

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

    public void setVip(boolean vip) {
        this.vip = vip;
    }

    public void setSvip(Boolean svip) {
        this.svip = svip;
    }
}
  • @ToString

重写toString方法。

源码:

@ToString
public class User {

    private String name;

    private long id;

    private Integer age;

    private boolean vip;

    private Boolean svip;

}

 编译后:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

public class User {
    private String name;
    private long id;
    private Integer age;
    private boolean vip;
    private Boolean svip;

    public User() {
    }

    public String toString() {
        return "User(name=" + this.name + ", id=" + this.id + ", age=" + this.age + ", vip=" + this.vip + ", svip=" + this.svip + ")";
    }
}
  • @EqualsAndHashCode

重写equals与hashcode方法。

源码:

@EqualsAndHashCode
public class User {

    private String name;

    private long id;

    private Integer age;

    private boolean vip;

    private Boolean svip;

}

编译后,从下面的方法可以看出,Lombok重写的方法会比较所有属性:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

public class User {
    private String name;
    private long id;
    private Integer age;
    private boolean vip;
    private Boolean svip;

    public User() {
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof User)) {
            return false;
        } else {
            User other = (User)o;
            if (!other.canEqual(this)) {
                return false;
            } else if (this.id != other.id) {
                return false;
            } else if (this.vip != other.vip) {
                return false;
            } else {
                label52: {
                    Object this$age = this.age;
                    Object other$age = other.age;
                    if (this$age == null) {
                        if (other$age == null) {
                            break label52;
                        }
                    } else if (this$age.equals(other$age)) {
                        break label52;
                    }

                    return false;
                }

                Object this$svip = this.svip;
                Object other$svip = other.svip;
                if (this$svip == null) {
                    if (other$svip != null) {
                        return false;
                    }
                } else if (!this$svip.equals(other$svip)) {
                    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 User;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        long $id = this.id;
        int result = result * 59 + (int)($id >>> 32 ^ $id);
        result = result * 59 + (this.vip ? 79 : 97);
        Object $age = this.age;
        result = result * 59 + ($age == null ? 43 : $age.hashCode());
        Object $svip = this.svip;
        result = result * 59 + ($svip == null ? 43 : $svip.hashCode());
        Object $name = this.name;
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }
}
  • @AllArgsConstructor、@NoArgsConstructor

@AllArgsConstructor构建全参构造器,@NoArgsConstructor构建无参构造器。

源码:

@AllArgsConstructor
@NoArgsConstructor
public class User {

    private String name;

    private long id;

    private Integer age;

    private boolean vip;

    private Boolean svip;

}

编译后:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

public class User {
    private String name;
    private long id;
    private Integer age;
    private boolean vip;
    private Boolean svip;

    public User(String name, long id, Integer age, boolean vip, Boolean svip) {
        this.name = name;
        this.id = id;
        this.age = age;
        this.vip = vip;
        this.svip = svip;
    }

    public User() {
    }
}
  • @Builder

对Bean构建Builder构建者模式。

源码:

@Builder
public class User {

    private String name;

    private long id;

    private Integer age;

    private boolean vip;

    private Boolean svip;

}

编译后:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

public class User {
    private String name;
    private long id;
    private Integer age;
    private boolean vip;
    private Boolean svip;

    User(String name, long id, Integer age, boolean vip, Boolean svip) {
        this.name = name;
        this.id = id;
        this.age = age;
        this.vip = vip;
        this.svip = svip;
    }

    public static User.UserBuilder builder() {
        return new User.UserBuilder();
    }

    public static class UserBuilder {
        private String name;
        private long id;
        private Integer age;
        private boolean vip;
        private Boolean svip;

        UserBuilder() {
        }

        public User.UserBuilder name(String name) {
            this.name = name;
            return this;
        }

        public User.UserBuilder id(long id) {
            this.id = id;
            return this;
        }

        public User.UserBuilder age(Integer age) {
            this.age = age;
            return this;
        }

        public User.UserBuilder vip(boolean vip) {
            this.vip = vip;
            return this;
        }

        public User.UserBuilder svip(Boolean svip) {
            this.svip = svip;
            return this;
        }

        public User build() {
            return new User(this.name, this.id, this.age, this.vip, this.svip);
        }

        public String toString() {
            return "User.UserBuilder(name=" + this.name + ", id=" + this.id + ", age=" + this.age + ", vip=" + this.vip + ", svip=" + this.svip + ")";
        }
    }
}
  • @Cleanup

用于局部变量,会调用变量的close方法来关闭资源。@Cleanup标记的局部变量,必须具有close方法。

源码:

public void method() throws IOException {
    @Cleanup FileOutputStream fileOutputStream = new FileOutputStream("E:\\Downloads\\java.txt");
    fileOutputStream.write("Hello World".getBytes());
}

编译后:

public void method() throws IOException {
    FileOutputStream fileOutputStream = new FileOutputStream("E:\\Downloads\\java.txt");

    try {
        fileOutputStream.write("Hello World".getBytes());
    } finally {
        if (Collections.singletonList(fileOutputStream).get(0) != null) {
            fileOutputStream.close();
        }

    }

}
  • @NonNull

非空检查,当设置的值为空时,会抛异常。

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

调用,对name进行赋值为null:

User user = new User();
user.setName(null);

抛异常:

  • @RequiredArgsConstructor

对标记了@NonNull的属性构建有参构造器。

源码:

@RequiredArgsConstructor
public class User {

    @NonNull
    private String name;

    private long id;

    private Integer age;

    @NonNull
    private boolean vip;

    private Boolean svip;

}

编译后,从这里可以看出@NonNull标注的字段会加非空判断:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import lombok.NonNull;

public class User {
    @NonNull
    private String name;
    private long id;
    private Integer age;
    @NonNull
    private boolean vip;
    private Boolean svip;

    public User(@NonNull String name, @NonNull boolean vip) {
        if (name == null) {
            throw new NullPointerException("name is marked non-null but is null");
        } else {
            this.name = name;
            this.vip = vip;
        }
    }
}
  • @Data

作用是@Getter、@Setter、@ToString、@EqualsAndHashCode、@RequiredArgsConstructor的聚合。

源码:

@Data
public class User {

    private String name;

    private long id;

    private Integer age;

    private boolean vip;

    private Boolean svip;

}

编译后:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import java.util.List;
import lombok.NonNull;

public class User {
    @NonNull
    private String name;
    private long id;
    private Integer age;
    private boolean vip;
    private Boolean svip;
    private List<String> list;

    public User(@NonNull String name) {
        if (name == null) {
            throw new NullPointerException("name is marked non-null but is null");
        } else {
            this.name = name;
        }
    }

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

    public long getId() {
        return this.id;
    }

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

    public boolean isVip() {
        return this.vip;
    }

    public Boolean getSvip() {
        return this.svip;
    }

    public List<String> getList() {
        return this.list;
    }

    public void setName(@NonNull String name) {
        if (name == null) {
            throw new NullPointerException("name is marked non-null but is null");
        } else {
            this.name = name;
        }
    }

    public void setId(long id) {
        this.id = id;
    }

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

    public void setVip(boolean vip) {
        this.vip = vip;
    }

    public void setSvip(Boolean svip) {
        this.svip = svip;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

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

                    return false;
                }

                label57: {
                    Object this$svip = this.getSvip();
                    Object other$svip = other.getSvip();
                    if (this$svip == null) {
                        if (other$svip == null) {
                            break label57;
                        }
                    } else if (this$svip.equals(other$svip)) {
                        break label57;
                    }

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

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

                return true;
            }
        }
    }

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

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        long $id = this.getId();
        int result = result * 59 + (int)($id >>> 32 ^ $id);
        result = result * 59 + (this.isVip() ? 79 : 97);
        Object $age = this.getAge();
        result = result * 59 + ($age == null ? 43 : $age.hashCode());
        Object $svip = this.getSvip();
        result = result * 59 + ($svip == null ? 43 : $svip.hashCode());
        Object $name = this.getName();
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        Object $list = this.getList();
        result = result * 59 + ($list == null ? 43 : $list.hashCode());
        return result;
    }

    public String toString() {
        return "User(name=" + this.getName() + ", id=" + this.getId() + ", age=" + this.getAge() + ", vip=" + this.isVip() + ", svip=" + this.getSvip() + ", list=" + this.getList() + ")";
    }
}
  • @SneakyThrows

标记方法抛出的异常。

源码:

@SneakyThrows(IOException.class)
public void method() {
    FileOutputStream fileOutputStream = new FileOutputStream("E:\\Downloads\\java.txt");
    fileOutputStream.write("Hello World".getBytes());
}

编译后:

public void method() {
    try {
        FileOutputStream fileOutputStream = new FileOutputStream("E:\\Downloads\\java.txt");
        fileOutputStream.write("Hello World".getBytes());
    } catch (IOException var2) {
        throw var2;
    }
}
  • @Synchronized

对方法体进行同步操作。

源码:

@Synchronized
public void method() throws IOException{
    FileOutputStream fileOutputStream = new FileOutputStream("E:\\Downloads\\java.txt");
    fileOutputStream.write("Hello World".getBytes());
}

编译后:

private final Object $lock = new Object[0];

public void method() throws IOException {
    synchronized(this.$lock) {
        FileOutputStream fileOutputStream = new FileOutputStream("E:\\Downloads\\java.txt");
        fileOutputStream.write("Hello World".getBytes());
    }
}
  • @Value

构建一个final修饰的类,并提供全参构造器,getter方法,重新equals、hashcode、toString方法。

源码:

@Value
public class User {

    private String name;

    private long id;

    private Integer age;

    private boolean vip;

    private Boolean svip;

}

编译后:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

public final class User {
    private final String name;
    private final long id;
    private final Integer age;
    private final boolean vip;
    private final Boolean svip;

    public User(String name, long id, Integer age, boolean vip, Boolean svip) {
        this.name = name;
        this.id = id;
        this.age = age;
        this.vip = vip;
        this.svip = svip;
    }

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

    public long getId() {
        return this.id;
    }

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

    public boolean isVip() {
        return this.vip;
    }

    public Boolean getSvip() {
        return this.svip;
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof User)) {
            return false;
        } else {
            User other = (User)o;
            if (this.getId() != other.getId()) {
                return false;
            } else if (this.isVip() != other.isVip()) {
                return false;
            } else {
                label49: {
                    Object this$age = this.getAge();
                    Object other$age = other.getAge();
                    if (this$age == null) {
                        if (other$age == null) {
                            break label49;
                        }
                    } else if (this$age.equals(other$age)) {
                        break label49;
                    }

                    return false;
                }

                Object this$svip = this.getSvip();
                Object other$svip = other.getSvip();
                if (this$svip == null) {
                    if (other$svip != null) {
                        return false;
                    }
                } else if (!this$svip.equals(other$svip)) {
                    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;
            }
        }
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        long $id = this.getId();
        int result = result * 59 + (int)($id >>> 32 ^ $id);
        result = result * 59 + (this.isVip() ? 79 : 97);
        Object $age = this.getAge();
        result = result * 59 + ($age == null ? 43 : $age.hashCode());
        Object $svip = this.getSvip();
        result = result * 59 + ($svip == null ? 43 : $svip.hashCode());
        Object $name = this.getName();
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }

    public String toString() {
        return "User(name=" + this.getName() + ", id=" + this.getId() + ", age=" + this.getAge() + ", vip=" + this.isVip() + ", svip=" + this.getSvip() + ")";
    }
}
  • @With

构建一个withXX的方法,实现将参数比较,如果是相等,返回当前对象,如果不等,创建新的对象。@With标记的类必须提供一个全参构造器,否则无法编译通过(为什么呢?看完编译后的源码就清楚了)。

源码:

@AllArgsConstructor
@With
public class User {

    private String name;

    public User(String name) {
        this.name = name;
    }

    private long id;

    private Integer age;

    private boolean vip;

    private Boolean svip;

}

编译后:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

public class User {
    private String name;
    private long id;
    private Integer age;
    private boolean vip;
    private Boolean svip;

    public User(String name) {
        this.name = name;
    }

    public User(String name, long id, Integer age, boolean vip, Boolean svip) {
        this.name = name;
        this.id = id;
        this.age = age;
        this.vip = vip;
        this.svip = svip;
    }

    public User withName(String name) {
        // 通过new User的全参构造器创建对象的,所以必须提供一个全参构造器
        return this.name == name ? this : new User(name, this.id, this.age, this.vip, this.svip);
    }

    public User withId(long id) {
        return this.id == id ? this : new User(this.name, id, this.age, this.vip, this.svip);
    }

    public User withAge(Integer age) {
        return this.age == age ? this : new User(this.name, this.id, age, this.vip, this.svip);
    }

    public User withVip(boolean vip) {
        return this.vip == vip ? this : new User(this.name, this.id, this.age, vip, this.svip);
    }

    public User withSvip(Boolean svip) {
        return this.svip == svip ? this : new User(this.name, this.id, this.age, this.vip, svip);
    }
}
  • var、val

声明局部变量。

源码:

public void method() {
    var x = 10;
    val y = 1.1;
    var list = new ArrayList<>();
    list.add("hello world");
}

编译后:

public void method() {
    int x = true;
    double y = 1.1D;
    ArrayList<Object> list = new ArrayList();
    list.add("hello world");
}
  • @CommonsLog

日志相关,构建log字段,类型为org.apache.commons.logging.Log。使用的时候要引入相对应的日志依赖。

源码:

@CommonsLog
public class User {
    
}

编译后:

public class User {

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

}
  • @Flogger、@JBossLog、@Log、@Log4j、@Log4j2、@Slf4j、@XSlf4j

和@CommonsLog一样都是日志相关,区别是Log类型不同。

@Flogger:

private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass();

@JBossLog:

private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(User.class);

@Log:

private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(User.class.getName());

@Log4j:

private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(User.class);

@Log4j2:

private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(User.class);

@Slf4j:

private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(User.class);

@XSlf4j:

private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(User.class);


关于Lombok的详细介绍,请戳《Lombok-高级篇

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值