lombok的简单使用
1.Eclipse安装插件
0.可以用maven引入依赖之后用maven下载相关jar包
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <scope>provided</scope> </dependency>
1.找到lombok-1.18.12.jar
java -jar ./lombok-1.18.12.jar
2.选择Eclipse对应的安装位置之后安装
3.安装成功在eclipse目录会生成lombok.jar
同时eclipse.ini也会增加一行:
-javaagent:E:\Eclipse\eclipse-jee-mars-1-win32-x86_64\eclipse-jee-mars-1-win32-x86_64\eclipse\lombok.jar
4.重启eclipse即可
二、IDEA安装
打开Idea, 左上角菜单选择 ”File --> Settings", 在弹出的对话框中,左侧选择Plugins,搜索栏输入'lombok', 然后点击安装,如下图:
安装完重启即可。
三、lombok简单使用
pom文件引入依赖:(注意其依赖范围是provided-编译(compile)时需要,测试(test)时也需要 ,运行时不需要,打包时不需要)
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <scope>provided</scope> </dependency>
1.测试常用注解@Getter、@Setter、@EqualsAndHashCode、@ToString
package cn.qlq.lombok; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import lombok.ToString; @Getter @Setter @EqualsAndHashCode @ToString public class User { private long id; private String username; }
jd反编译后查看代码:
package cn.qlq.lombok; public class User { private long id; private String username; public String getUsername() { return this.username; } public long getId() { return this.id; } public void setUsername(String username) { this.username = username; } public void setId(long id) { this.id = id; } protected boolean canEqual(Object other) { return other instanceof User; } public int hashCode() { int PRIME = 59;int result = 1;long $id = getId();result = result * 59 + (int)($id ^ $id >>> 32);Object $username = getUsername();result = result * 59 + ($username == null ? 43 : $username.hashCode());return result; } public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof User)) { return false; } User other = (User)o; if (!other.canEqual(this)) { return false; } if (getId() != other.getId()) { return false; } Object this$username = getUsername();Object other$username = other.getUsername();return this$username == null ? other$username == null : this$username.equals(other$username); } public String toString() { return "User(id=" + getId() + ", username=" + getUsername() + ")"; } }
2.@NoArgsConstructor 、@AllArgsConstructor分别用于无参构造和有参构造
package cn.qlq.lombok; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; @NoArgsConstructor // 无参构造 @AllArgsConstructor // 有参构造 public class User { private long id; private String username; }
反编译查看代码:
package cn.qlq.lombok; public class User { private long id; private String username; public User() {} public User(long id, String username) { this.id = id;this.username = username; } }
3.@Data 相当于@Getter、@Setter、@EqualsAndHashCode、@ToString
package cn.qlq.lombok; import lombok.Data; @Data public class User { private long id; private String username; }
反编译查看:
package cn.qlq.lombok; public class User { private long id; private String username; public String toString() { return "User(id=" + getId() + ", username=" + getUsername() + ")"; } public int hashCode() { int PRIME = 59;int result = 1;long $id = getId();result = result * 59 + (int)($id ^ $id >>> 32);Object $username = getUsername();result = result * 59 + ($username == null ? 43 : $username.hashCode());return result; } protected boolean canEqual(Object other) { return other instanceof User; } public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof User)) { return false; } User other = (User)o; if (!other.canEqual(this)) { return false; } if (getId() != other.getId()) { return false; } Object this$username = getUsername();Object other$username = other.getUsername();return this$username == null ? other$username == null : this$username.equals(other$username); } public void setUsername(String username) { this.username = username; } public void setId(long id) { this.id = id; } public String getUsername() { return this.username; } public long getId() { return this.id; } }
查看@Data源码如下:其实还有@RequiredArgsConstructor ,只是这个注解一般不用。
/** <a href="http://www.cpupk.com/decompiler">Eclipse Class Decompiler</a> plugin, Copyright (c) 2017 Chen Chao. */ package lombok; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Generates getters for all fields, a useful toString method, and hashCode and equals implementations that check * all non-transient fields. Will also generate setters for all non-final fields, as well as a constructor. * <p> * Equivalent to {@code @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode}. * <p> * Complete documentation is found at <a href="https://projectlombok.org/features/Data">the project lombok features page for @Data</a>. * * @see Getter * @see Setter * @see RequiredArgsConstructor * @see ToString * @see EqualsAndHashCode * @see lombok.Value */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface Data { /** * If you specify a static constructor name, then the generated constructor will be private, and * instead a static factory method is created that other classes can use to create instances. * We suggest the name: "of", like so: * * <pre> * public @Data(staticConstructor = "of") class Point { final int x, y; } * </pre> * * Default: No static constructor, instead the normal constructor is public. * * @return Name of static 'constructor' method to generate (blank = generate a normal constructor). */ String staticConstructor() default ""; }
需要注意:@Data生成toString和equals、hashCode时不会选择父类的字段,如下:
父类:
package cn.qlq.lombok; import java.io.Serializable; import lombok.Data; @Data public abstract class AbstractSequenceEntity implements Serializable { private static final long serialVersionUID = 7304379208787774552L; protected Long id; }
反编译查看:
package cn.qlq.lombok; import java.io.Serializable; public abstract class AbstractSequenceEntity implements Serializable { private static final long serialVersionUID = 7304379208787774552L; protected Long id; public String toString() { return "AbstractSequenceEntity(id=" + getId() + ")"; } public int hashCode() { int PRIME = 59;int result = 1;Object $id = getId();result = result * 59 + ($id == null ? 43 : $id.hashCode());return result; } protected boolean canEqual(Object other) { return other instanceof AbstractSequenceEntity; } public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof AbstractSequenceEntity)) { return false; } AbstractSequenceEntity other = (AbstractSequenceEntity)o; if (!other.canEqual(this)) { return false; } Object this$id = getId();Object other$id = other.getId();return this$id == null ? other$id == null : this$id.equals(other$id); } public void setId(Long id) { this.id = id; } public Long getId() { return this.id; } }
子类如下:
package cn.qlq.lombok; import lombok.Data; @Data public class User extends AbstractSequenceEntity { private static final long serialVersionUID = 1487903039867324395L; private String username; }
反编译查看:没有从父类继承的属性
package cn.qlq.lombok; public class User extends AbstractSequenceEntity { private static final long serialVersionUID = 1487903039867324395L; private String username; public String toString() { return "User(username=" + getUsername() + ")"; } public int hashCode() { int PRIME = 59;int result = 1;Object $username = getUsername();result = result * 59 + ($username == null ? 43 : $username.hashCode());return result; } protected boolean canEqual(Object other) { return other instanceof User; } public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof User)) { return false; } User other = (User)o; if (!other.canEqual(this)) { return false; } Object this$username = getUsername();Object other$username = other.getUsername();return this$username == null ? other$username == null : this$username.equals(other$username); } public void setUsername(String username) { this.username = username; } public String getUsername() { return this.username; } }
解决办法:
package cn.qlq.lombok; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import lombok.ToString; @Getter @Setter // callSuper: 是否包含父类的属性 @ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class User extends AbstractSequenceEntity { private static final long serialVersionUID = 1487903039867324395L; private String username; }
反编译查看:
package cn.qlq.lombok; public class User extends AbstractSequenceEntity { private static final long serialVersionUID = 1487903039867324395L; private String username; public String getUsername() { return this.username; } public void setUsername(String username) { this.username = username; } public String toString() { return "User(super=" + super.toString() + ", username=" + getUsername() + ")"; } public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof User)) { return false; } User other = (User)o; if (!other.canEqual(this)) { return false; } if (!super.equals(o)) { return false; } Object this$username = getUsername();Object other$username = other.getUsername();return this$username == null ? other$username == null : this$username.equals(other$username); } protected boolean canEqual(Object other) { return other instanceof User; } public int hashCode() { int PRIME = 59;int result = super.hashCode();Object $username = getUsername();result = result * 59 + ($username == null ? 43 : $username.hashCode());return result; } }
4.@Slf4j可以整合日志
原来我们使用日志的方式如下:
package cn.qlq.lombok; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class User { private static final Logger log = LoggerFactory.getLogger(User.class); }
注解方式如下:
package cn.qlq.lombok; import lombok.extern.slf4j.Slf4j; @Slf4j public class User { }
反编译查看:
package cn.qlq.lombok; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class User { private static final Logger log = LoggerFactory.getLogger(User.class); }
5.@Builder用于生成加个构造者模式
package cn.qlq.lombok; import lombok.Builder; import lombok.Data; @Data @Builder public class User { private long id; private String username; }
测试代码:
package cn.qlq.lombok; public class Client { public static void main(String[] args) { // 两种方式创建Builder // UserBuilder builder = User.builder(); User.UserBuilder userBuilder = new User.UserBuilder(); User user = userBuilder.id(5).username("admin").build(); System.out.println(user); } }
结果:
User(id=5, username=admin)
反编译查看:(User$UserBuilder.class是内部类编译后生成的cass文件)
package cn.qlq.lombok; public class User { private long id; private String username; public String toString() { return "User(id=" + getId() + ", username=" + getUsername() + ")"; } public int hashCode() { int PRIME = 59;int result = 1;long $id = getId();result = result * 59 + (int)($id ^ $id >>> 32);Object $username = getUsername();result = result * 59 + ($username == null ? 43 : $username.hashCode());return result; } protected boolean canEqual(Object other) { return other instanceof User; } public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof User)) { return false; } User other = (User)o; if (!other.canEqual(this)) { return false; } if (getId() != other.getId()) { return false; } Object this$username = getUsername();Object other$username = other.getUsername();return this$username == null ? other$username == null : this$username.equals(other$username); } public void setUsername(String username) { this.username = username; } public void setId(long id) { this.id = id; } public String getUsername() { return this.username; } public long getId() { return this.id; } public static class UserBuilder { private long id; private String username; public String toString() { return "User.UserBuilder(id=" + this.id + ", username=" + this.username + ")"; } public User build() { return new User(this.id, this.username); } public UserBuilder username(String username) { this.username = username;return this; } public UserBuilder id(long id) { this.id = id;return this; } } public static UserBuilder builder() { return new UserBuilder(); } User(long id, String username) { this.id = id;this.username = username; } }
package cn.qlq.lombok; public class User$UserBuilder { private long id; private String username; public String toString() { return "User.UserBuilder(id=" + this.id + ", username=" + this.username + ")"; } public User build() { return new User(this.id, this.username); } public UserBuilder username(String username) { this.username = username;return this; } public UserBuilder id(long id) { this.id = id;return this; } }
6. 注解 @Accessors 用于定义链式调用
1. 源码
package lombok.experimental; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE, ElementType.FIELD}) @Retention(RetentionPolicy.SOURCE) public @interface Accessors { boolean fluent() default false; boolean chain() default false; String[] prefix() default {}; }
解释:chain 用于setter 方法完成之后是否返回this, 也就是允许链式调用; fluent 为true 的情况下,setter 方法不带set、getter 方法不带get, 直接就是属性名称。比如:
@Data @Accessors(fluent = true, chain = true) public class User { private String username; private int age; }
反编译查看生成的类信息:
package cn; public class User { private String username; private int age; public User() { } public String username() { return this.username; } public int age() { return this.age; } public User username(final String username) { this.username = username; return this; } public User age(final int age) { this.age = age; return this; } public boolean equals(final 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.age() != other.age()) { return false; } else { Object this$username = this.username(); Object other$username = other.username(); 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 User; } public int hashCode() { int PRIME = true; int result = 1; int result = result * 59 + this.age(); Object $username = this.username(); result = result * 59 + ($username == null ? 43 : $username.hashCode()); return result; } public String toString() { String var10000 = this.username(); return "User(username=" + var10000 + ", age=" + this.age() + ")"; } }
补充一些其他不常用的注解:
@Cleanup : 可以关闭流
@Synchronized : 加个同步锁
@SneakyThrows : 等同于try/catch 捕获异常
@NonNull : 如果给参数加个这个注解 参数为null会抛出空指针异常
@Value : 注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法。
@RequiredArgsConstructor:相当于属性生成构造方法,在spring 上下文环境相当于构造注入。
补充:@SneakyThrows 的简单用法
简单的说,它就是可以try。。catch。。。 然后向上抛异常。比如:
package qz; import lombok.SneakyThrows; import java.io.UnsupportedEncodingException; public class Test { public static void main(String[] args) { test(); test2(); } // 常规写法 private static void test() { try { String gg = new String("124".getBytes("ff")); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } // 使用SneakyThrows 的写法 @SneakyThrows private static void test2() { String gg = new String("124".getBytes("ff")); } }
查看反编译后的class:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package qz; import java.io.UnsupportedEncodingException; public class Test { public Test() { } public static void main(String[] args) { test(); test2(); } private static void test() { try { new String("124".getBytes("ff")); } catch (UnsupportedEncodingException var1) { throw new RuntimeException(var1); } } private static void test2() { try { new String("124".getBytes("ff")); } catch (Throwable var1) { throw var1; } } }
主要看test2()方法,如果代码中直接这么写还编译不过去,lombok巧妙的骗过编译器,使其编译过去,不过多研究,简单记录会使用即可。
补充: 关于父类、子类使用builder
1、 两个builder ```xml package qz.lombok; import lombok.*; @Data @Builder @AllArgsConstructor @NoArgsConstructor @ToString public class Parent { private String name; private int age; } package qz.lombok; import lombok.*; @Data @Builder @AllArgsConstructor @NoArgsConstructor @ToString public class Parent { private String name; private int age; } package qz.lombok; public class Client { public static void main(String[] args) { Parent play = Children.builder().name("play").age(2).build(); System.out.println(play); System.out.println(Children.childBuilder().likes("play").build()); } } Parent(name=play, age=2) Children(likes=play) ``` 查看编译后的类 ```xml // // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package qz.lombok; public class Parent { private String name; private int age; public static ParentBuilder builder() { return new ParentBuilder(); } public String getName() { return this.name; } public int getAge() { return this.age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof Parent)) { return false; } else { Parent other = (Parent)o; if (!other.canEqual(this)) { return false; } else if (this.getAge() != other.getAge()) { return false; } else { 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 Parent; } public int hashCode() { int PRIME = true; int result = 1; result = result * 59 + this.getAge(); Object $name = this.getName(); result = result * 59 + ($name == null ? 43 : $name.hashCode()); return result; } public Parent(String name, int age) { this.name = name; this.age = age; } public Parent() { } public String toString() { return "Parent(name=" + this.getName() + ", age=" + this.getAge() + ")"; } public static class ParentBuilder { private String name; private int age; ParentBuilder() { } public ParentBuilder name(String name) { this.name = name; return this; } public ParentBuilder age(int age) { this.age = age; return this; } public Parent build() { return new Parent(this.name, this.age); } public String toString() { return "Parent.ParentBuilder(name=" + this.name + ", age=" + this.age + ")"; } } } --- 子 // // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package qz.lombok; public class Children extends Parent { private String likes; public Children(String likes) { this.likes = likes; } public static ChildrenBuilder childBuilder() { return new ChildrenBuilder(); } public String getLikes() { return this.likes; } public void setLikes(String likes) { this.likes = likes; } public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof Children)) { return false; } else { Children other = (Children)o; if (!other.canEqual(this)) { return false; } else { Object this$likes = this.getLikes(); Object other$likes = other.getLikes(); if (this$likes == null) { if (other$likes != null) { return false; } } else if (!this$likes.equals(other$likes)) { return false; } return true; } } } protected boolean canEqual(Object other) { return other instanceof Children; } public int hashCode() { int PRIME = true; int result = 1; Object $likes = this.getLikes(); result = result * 59 + ($likes == null ? 43 : $likes.hashCode()); return result; } public Children() { } public String toString() { return "Children(likes=" + this.getLikes() + ")"; } public static class ChildrenBuilder { private String likes; ChildrenBuilder() { } public ChildrenBuilder likes(String likes) { this.likes = likes; return this; } public Children build() { return new Children(this.likes); } public String toString() { return "Children.ChildrenBuilder(likes=" + this.likes + ")"; } } } ``` 2、也可以使用 SuperBuilder ```java --- 父 package qz.lombok; import lombok.*; import lombok.experimental.SuperBuilder; @Data @SuperBuilder @AllArgsConstructor @NoArgsConstructor @ToString public class Parent { private String name; private int age; } --- 子 package qz.lombok; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; import lombok.experimental.SuperBuilder; @Data @NoArgsConstructor @ToString(callSuper = true) @SuperBuilder public class Children extends Parent { private String likes; } --- client package qz.lombok; public class Client { public static void main(String[] args) { Children play = Children.builder().name("play").age(2).likes("11").build(); System.out.println(play); Parent play2 = Parent.builder().name("play").age(2).build(); System.out.println(play2); } } --- 结果 Children(super=Parent(name=play, age=2), likes=11) Parent(name=play, age=2) ```