Java编辑器现在有一个Lombok的插件,使用非常方便,IDEA、Eclipse都有对应的插件。
Lombok能通过注解的方式,在编译时自动为类属性生成 构造方法、getter()、setter()、equals()、hashcode()、toString()方法。
这样你写代码就只用关注类属性,对应的以上方法会在编译时自动生成。这样节省了代码量,也使代码看起来更简洁些,即使哪天更改属性名、添加删除属性名 这些方法也会自动更新。
实际项目中看到如下使用片段:
/**
* xx信息
*
* @Author wanglingqiang
* @Date 2020/6/30 上午10:01
**/
@Data
@ApiModel(value = "Team(xx信息)")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
public class Team implements Serializable {
private static final long serialVersionUID = 7618841591717042342L;
// ...其他类属性
类上Lombok相关的注解有:
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
Entity、DTO、VO类建好后,如上的注解大家都是直接拷贝(至于这些注解都是干嘛的,不知道!别人这么用,我也这么用呗)。但心里还是不放心,于是自己写Demo测试了一下。
@Data:是Lombok的基础注解,这个不用说了。
接下来说说另外两个注解:
@Accessors注解
@Accessors(chain = true)
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE)
public @interface Accessors {
boolean fluent() default false;
boolean chain() default false;
String[] prefix() default {};
}
chain默认值是false,与true有什么区别呢?
值为true时,setXxx()方法返回的是对象,方便链式调用。比如:team.setTeamNo(“T001”).setTeamName(“Team1”)。
值为false时,setXxx()方法返回的是void。
@Accessors(fluent = true)
fluent 默认值是false,与true有什么区别呢?
getXxx()方法变成了xxx()。
setXxx(String xx)方法变成了xxx(String xx)。
@Accessors(fluent = true) 总结,get/set方法去掉了get、set的前缀,直接使用属性名作为方法名。
@Accessors(prefix = “xxx”)
从语义上理解是前缀的意思,我们来试试它怎么实现前缀的。
没加prefix属性前,可以看到是常规的getXxx()、setXxx()。
在teamNo属性上加前缀“team”,
@Accessors(prefix = "team")
private String teamNo;
再看看teamNo属性的getXxx()、setXxx() ,如下:
发现了没,teamNo生成的getXxx()、setXxx()去掉了prefix = "team"的“team”前缀。
总结:
1.如果@Accessors(prefix = “xxx”)作用在类上,会对类的所有属性起作用。
2.如果@Accessors(prefix = “xxx”)作用在属性上,只会对当前属性起作用。
3.prefix 的值"xxx"全部小写,比如getTeamNo(),想要的效果是getNo(),那么prefix="team"才行。“Team”、“teaM”都会匹配不上。
@EqualsAndHashCode
接下来,再看看我们代码里的 @EqualsAndHashCode(callSuper = false)是什么用意。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface EqualsAndHashCode {
String[] exclude() default {};
String[] of() default {};
boolean callSuper() default false;
boolean doNotUseGetters() default false;
callSuper默认值就是false,所以说我们代码里面写这一行是多余的。
通过示例理解该注解:
/**
* 分页公共类(父类)
*
* @author wanglingqiang
* @date 2020/7/16 下午6:25
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Page {
private Integer current = 1; //当前页
private Integer size = 10; //每页数量
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User extends Page {
private Integer id;
private String name;
public User(Integer current, Integer size, Integer id, String name) {
super(current, size);
this.id = id;
this.name = name;
}
}
User继承Page,因为callSuper默认值是false,即User的@EqualsAndHashCode(callSuper = false)。
测试类:
public class Test {
public static void main(String[] args) {
User user1 = new User(1, 10, 1, "张三");
User user2 = new User(2, 10, 1, "张三");
boolean flag = user1.equals(user2);
System.out.println("flag = " + flag);
}
}
@EqualsAndHashCode(callSuper = false)时,运行结果:
flag = true
奇怪不,明明属性值不一样,但equal()比较时竟然相等。
@EqualsAndHashCode(callSuper = true)时,运行结果:
flag = false
可以看出,callSuper = true时,子类在重写hashcode()和equals()方法时才会调用父类的属性,即把父类属性包含在一起重写hashcode()和equals()方法。
callSuper有它的实用场景,为true、为false可以根据实际需要设值。
@NoArgsConstructor、@AllArgsConstructor
上面的示例中还有两个Lombok注释:
@NoArgsConstructor
@AllArgsConstructor
这两个注解比较加单,从语义上就能理解,是生成构造方法用的。写上这两个注解的效果,如图: