Lombok
1、简单概述
工作中大量重复毫无技术的去书写get()、set()方法,不推荐手写,也不推荐利用idea中的工具类等等操作
而是使用lombok中的注解来一套搞定。
既然lombok能够搞定,那么需要理解一下是如何来搞定这一切的。
lombok除了get/set,还有一些其他的可以使用的。
可以去看一下官网:
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中的冗长代码(也就是毫无技术可言的重复性工作),尤其是对于简单的java对象(POJO),通过注解实现这一目的。
Lombok可以简化我们的代码书写方式。
Lombok的原理:
JSR269:插件化注解处理API
JDK6提供的特性,在javac编译期间利用注解搞事情。在编译期间可以利用lombok的注解方式来进行将生成的代码添加到字节码文件中去。我们利用Lombok注解生成的字节码文件中是包含了的。
二、使用
最常用的注解
2.1、@Data
可以自动的帮助我们生成get/seter、toString、hashcode和equals方法,但是呢,我们可以看到这种使用方式:
@Data
public class User {
private String name;
}
在idea中看到对应的class目录:
public class User {
private String name;
public User() {
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
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 {
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 User;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $name = this.getName();
int result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
public String toString() {
return "User(name=" + this.getName() + ")";
}
}
可以看到其中的方法已经在上面对应好了,而且生成的还是当前类中的属性。
但是问题就出现在这里,我再写一个父类:
@Data
public class Person {
private Integer id;
}
然后让其子类来进行继承:
@Data
@EqualsAndHashCode(callSuper = true)
public class User extends Person{
private String name;
}
编译后的Java如下所示:
public class User extends Person {
private String name;
public User() {
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "User(name=" + this.getName() + ")";
}
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 (!super.equals(o)) {
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 User;
}
public int hashCode() {
int PRIME = true;
int result = super.hashCode();
Object $name = this.getName();
result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
}
可以看到在equals方法中多了一个判断
if (!super.equals(o))
return false;
@EqualsAndHashCode(callSuper = true)的作用就在于将子类和父类中的属性都来进行比较,举个例子进行说明:
父类Person:
@Data
public class Person {
private Integer id;
}
子类User:
@Data
public class User extends Person{
private String name;
}
测试方法:
@Test
void contextLoads() {
User user1 = new User();
User user2= new User();
user1.setId(1);
user2.setId(2);
user1.setName("1");
user2.setName("1");
boolean equals = Objects.equals(user1, user2);
log.info("两个对象是否是相等的?------>{}",equals); //true
}
但是如果加了@EqualsAndHashCode(callSuper = true)
父类:
@Data
public class Person {
private Integer id;
}
子类:
@Data
@EqualsAndHashCode(callSuper = true)
public class User extends Person{
private String name;
}
再次运行测试类得到的却是false,那么为什么会有这样子的结果?
我们可以在不加@EqualsAndHashCode(callSuper = true)和不加的情况下分别看下class文件
2.2、@EqualsAndHashCode
不加@EqualsAndHashCode(callSuper = true)
public class User extends Person {
private String name;
public User() {
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
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 {
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 User;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $name = this.getName();
int result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
public String toString() {
return "User(name=" + this.getName() + ")";
}
}
加了@EqualsAndHashCode(callSuper = true)
public class User extends Person {
private String name;
public User() {
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "User(name=" + this.getName() + ")";
}
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 (!super.equals(o)) {
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 User;
}
public int hashCode() {
int PRIME = true;
int result = super.hashCode();
Object $name = this.getName();
result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
}
综合这两个情况来进行对比,可以看到加了@EqualsAndHashCode(callSuper = true)之后,生成的equals方法中多了一个判断:
if (!super.equals(o)) {
return false;
}
这里是在访问父类中的equals方法来进行判断,但是有时候我们希望使用到父类中的属性,有时候希望使用到子类中的属性。
所以我们需要根据当前的场景来进行选择,我现在使用的是直接将@EqualsAndHashCode(callSuper = false)
public class User extends Person {
private String name;
public User() {
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "User(name=" + this.getName() + ")";
}
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 {
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 User;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $name = this.getName();
int result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
}
可以看到这里和不加@EqualsAndHashCode是一样的,但是为了有些场景我们又需要不加上,所以需要根据自己的场景来进行判断
2.3、@Accessors
@Accessors(chain=true)
链式访问,该注解设置chain=true
,生成setter方法返回this,代替了默认的返回void。
@Data
@Accessors(chain=true)
public class User {
private Integer id;
private String name;
private Integer age;
public static void main(String[] args) {
User user=new User().setAge(31).setName("pollyduan");
System.out.println(user);
}
}
@Accessors(fluent = true)
与chain=true
类似,区别在于getter和setter不带set和get前缀。但是这个尽量不要使用,因为很多框架都是通过get/set方法来进行赋值的
@Data
@Accessors(fluent=true)
public class User {
private Integer id;
private String name;
private Integer age;
public static void main(String[] args) {
User user=new User().age(31).name("pollyduan");
System.out.println(user);
}
}
@Accessors(prefix = “f”)
去除掉属性的前缀之后生成的set方法:
@Data
@Accessors(prefix = "f")
public class User {
private String fName = "Hello, World!";
public static void main(String[] args) {
User user=new User();
user.setName("pollyduan");//注意方法名
System.out.println(user);
}
}
2.4、@NoArgsConstructor
无参构造
public User() {
}
2.5、@AllArgsConstructor
当前类中的属性的有参构造:
public User(String name) {
this.name = name;
}
2.6、@Builder
这个方法可以用也可以不用,我这里不用,做个记录。