为什么80%的码农都做不了架构师?>>>
Lombok
Idea添加插件:
项目中maven依赖,具体使用哪个版本可以自行去maven仓库找,学习时使用版本如下:
配置文件
特别注意:每当我们改过一次配置文件之后,需要clean一下功能,重新编译才能让配置生效。
lombok的配置文件需要放在src/main/java下面,放在resources下面是不生效的。
名称:lombok.config
大部分功能都有一个叫做lombok.xxx.flagUsage的配置,改配置是用来编译是检查的,如果配置了例如,
那么在使用注解@NonNull的时候,在编译时就会报ERROR。
官方文档:
https://projectlombok.org/features/all
val&var
val:定义出来的java类型是final的,val默认是开启的
var:定义出来的类型是非final的,默认改类型是未开启的,需要在配置文件中.如果在没有开启时使用,编译时不会报错,运行时会报错。
在配置文件中开启:
@NonNull
空值校验:
方法中的参数如果加了这个注解,会在调用方法是检验该参数,配置文件中可以配置校验失败时抛出的异常,只有两种,一种是NullPointerException,还有个是IllegalArgumentException,可以通过配置文件配置,如下:
#为空时抛出异常,默认为NullPointerException
lombok.nonNull.exceptionType=IllegalArgumentException
Java代码:
public class NotNullExample {public void get(@NonNull String a) {System.out.println(a);}public static void main(String[] args) {new NotNullExample().get(null);}
}
编译后(可以直接打看target中的class查看):
public class NotNullExample {public NotNullExample() {}public void get(@NonNull String a) {if (a == null) {throw new IllegalArgumentException("a is null");} else {System.out.println(a);}}public static void main(String[] args) {(new NotNullExample()).get((String)null);}
}
@CleanUp
退出前清除资源,例如inputstream.加了注解之后可以不用自己关闭,在调用结束之后会自动调用类的close()方法关闭该资源。默认是无参close()方法,如果是其他方法,可以通过参数指定:
Java代码:
public class CleanUpExample {public void close() {System.out.println("调用了close()方法");}public void myCloseMethod() {System.out.println("调用了myCloseMethod()方法");}public static void main(String[] args) {@Cleanup("myCloseMethod") CleanUpExample clean = new CleanUpExample();System.out.println("测试@CleanUp");}
}
编译后:
public class CleanUpExample {public CleanUpExample() {}public void close() {System.out.println("调用了close()方法");}public void myCloseMethod() {System.out.println("myCloseMethod()方法");}public static void main(String[] args) {CleanUpExample clean = new CleanUpExample();try {System.out.println("测试@CleanUp");} finally {if (Collections.singletonList(clean).get(0) != null) {clean.myCloseMethod();}}}
}
测试结果:
@Setter&@Getter
编译时自动为所有非static属性生成get和set方法,final属性不会生成set方法,使用时我们需要在类上面或者属性上面加@Getter或者@Setter注解。如果类上面个属性上面都配置了,那么属性上面配置的会覆盖掉类上面的。
value:指定生成的方法的性质,public还是private还是其他,值为NONE时忽略该属性。onMethod:方法上的注解格式onMethod=@__({@Myanon1,@Myanon2})onParam:参数上的注解(@Setter方法才有),格式同上lazy:字面意思
Java代码:
@Setter(value = AccessLevel.PUBLIC)
@Getter
public class GetterSetterExample {private final String finalStr = "";private static String staticStr;@Setter(AccessLevel.NONE)@Getter(AccessLevel.NONE)private String name;@Setter(value = AccessLevel.PUBLIC, onMethod = @__({@NonNull}), onParam = @__({@NonNull}))private Date birthday;@Accessors(prefix = "wt")private String wtFirstName;private boolean flag;public static void main(String[] args) {GetterSetterExample example = new GetterSetterExample();example.setBirthday(new Date());System.out.println(example.getBirthday());}
}
编译后:一部分get和set方法这里就不贴出来了,只留下了birthday的set方法。可以看到编译后注解都已经被加上了。
public class GetterSetterExample {private final String finalStr = "";private static String staticStr;private String name;private Date birthday;private String wtFirstName;private boolean flag;public GetterSetterExample() {}public String getFirstName() {return this.wtFirstName;}public boolean getFlag() {return this.flag;}@NonNullpublic void setBirthday(@NonNull Date birthday) {if (birthday == null) {throw new IllegalArgumentException("birthday is null");} else {this.birthday = birthday;}}
}
配置项:
lombok.accessors.chain = [true | false] (default: false)
配置改项为true后,生成的setter方法将返回this,而不是void,不贴代码了,代码里有。
lombok.accessors.fluent = [true | false] (default: false)
配置该项为true之后,生成的get和set方法将不再以get或set开头,而是和属性名字相同。
lombok.accessors.prefix += a field prefix (default: empty list)
注意这里是+=,不是=,配置该项之后属性生成get和set方法时将忽略指定的前缀,例如配置该项为wt,那么属性wtFirstName生成getFirstName(),改配置会对所有属性生效,如果其他属性不是以wt开头,这些属性就不会生成get,set方法。
以上三个属性都可以使用@Accessors注解来指定。
lombok.getter.noIsPrefix = [true | false] (default: false)
配置该项为true,boolean类型的生成的get方法不会以is开头,而是以get开头。
@ToString
重写toString()方法。默认情况下所有非static字段都会被打印。输出的内容包含类名,和所有属性的名称和值,任何以$符号开头的变量都会被自动排除,改注解同样可以使用到枚举类上面。
includeFieldNames:打印时是否输出属性的名字,默认为true。exclude:指定不输出的字段名。of:指定需要输出的字段名,of会覆盖掉exclude中相同的字段名。callSuper:是否调用超类的toString()方法,默认为false。doNotUseGetters:不使用get方法获取值,默认为false,即会调用get方法获取字段的值,当字段不存在get方法的时
候,也不会使用get方法获取该字段的值,不过建议将该值设置为true,即不使用get方法获取字段的值。
Java代码:
@ToString(includeFieldNames = true, exclude = {"name"}, callSuper = true, doNotUseGetters = false)
public class ToStringExample {private final String finalStr="finalStr";private static String staticStr="staticStr";private String name;@Getterprivate int age;@Toleratepublic static void main(String[] args) {ToStringExample example = new ToStringExample();example.age = 1;example.name = "hhh";System.out.println(example);}// @Override
// public String toString() {
// return "myToString()";
// }
}
编译后:
public class ToStringExample {private final String finalStr = "finalStr";private static String staticStr = "staticStr";private String name;private int age;public ToStringExample() {}public static void main(String[] args) {ToStringExample example = new ToStringExample();example.age = 1;example.name = "hhh";System.out.println(example);}public String toString() {return "ToStringExample(super=" + super.toString() + ", name=" + this.name + ", age=" + this.getAge() + ")";}public int getAge() {return this.age;}
}
配置文件:
lombok.toString.includeFieldNames = [true | false] (default: true)
lombok.toString.doNotUseGetters = [true | false] (default: false)
官方文档解释:
如果有一个名为toString的方法没有参数,无论返回类型是什么,都不会生成任何方法,而是发出一个警告,解释您的@toString注释什么都不做。您可以用@lombok.experimental.Tolerate来标记任何方法。容忍将他们从lombok中隐藏起来。默认情况下,任何以$符号开头的变量都会被自动排除,即不输出。
隐藏的意思是在类结构中看到此方法是灰色的,如图所示(main方法),但是是可用的,编译也会将此方法编译进去,同名方法将会被我们写的直接覆盖掉(已测试)。
@EqualsAndHashCode
属性跟ToString的差不多,除了callSuper不大一样,该注解的callSuper属性在父类为Object时会报错,即不允许父类为Object时使用callSuper.
Java代码:
@EqualsAndHashCode(onParam = @__({@NonNull}), doNotUseGetters = true)
public class EqualsAndHashCodeExample {private String name;private Integer age;public static void main(String[] args) {new EqualsAndHashCodeExample();}
}
编译后:
public class EqualsAndHashCodeExample {private String name;private Integer age;public EqualsAndHashCodeExample() {}public static void main(String[] args) {new EqualsAndHashCodeExample();}public boolean equals(@NonNull Object o) {if (o == null) {throw new IllegalArgumentException("o is null");} else if (o == this) {return true;} else if (!(o instanceof EqualsAndHashCodeExample)) {return false;} else {EqualsAndHashCodeExample other = (EqualsAndHashCodeExample)o;if (!other.canEqual(this)) {return false;} else {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;}Object this$age = this.age;Object other$age = other.age;if (this$age == null) {if (other$age != null) {return false;}} else if (!this$age.equals(other$age)) {return false;}return true;}}}protected boolean canEqual(@NonNull Object other) {return other instanceof EqualsAndHashCodeExample;}public int hashCode() {int PRIME = true;int result = 1;Object $name = this.name;int result = result * 59 + ($name == null ? 43 : $name.hashCode());Object $age = this.age;result = result * 59 + ($age == null ? 43 : $age.hashCode());return result;}
}
配置文件:
lombok.equalsAndHashCode.doNotUseGetters = [true | false] (default: false)
lombok.equalsAndHashCode.callSuper = [call | skip | warn] (default: warn)
lombok.equalsAndHashCode.flagUsage = [warning | error] (default: not set)
@XxxConstructor
@NoArgsConstructor:生成无参构造方法,如果类中有final类型的字段未初始化,编译时会报错,但是可以在改构造方法中将force设置为true,即强制生成,那么编译时不会报错,final的字段会在编译时自动设置为0/false/null.
@RequiredArgsConstructor :对所有初始化类的时候不会被初始化的属性生成构造方法,比如,如果属性为int,int初始化时为0,则不会对起该属性生成构造方法。属性上有@NonNull注解的生成检查代码。
@AllArgsConstructor:对所有非final,static属性生成构造方法,同样会对@NonNull属性生成检查代码。
以上三个注解的属性:
onConstructor:放在构造方法上的注解,格式onConstructor=@__{@MyAnon};access:构造方法公开性,public,private等;staticName:启用改属性,生成的构造方法将会变成private,然后会生成一个名称为该属性的值的静态方法,
该方法的公开性由access决定。
Java代码:
@NoArgsConstructor(staticName = "newInstence", access = AccessLevel.PROTECTED, onConstructor = @__({@MyAnon}))
@RequiredArgsConstructor
@AllArgsConstructor
public class XxxConstructorExample<T> {private final String a = "aaa";private static String b = "bbb";private T t;@NonNullprivate String name;private int age;
}
编译后:
public class XxxConstructorExample<T> {private final String a = "aaa";private static String b = "bbb";private T t;@NonNullprivate String name;private int age;@MyAnonprivate XxxConstructorExample() {}protected static <T> XxxConstructorExample<T> newInstence() {return new XxxConstructorExample();}@ConstructorProperties({"name"})public XxxConstructorExample(@NonNull String name) {if (name == null) {throw new IllegalArgumentException("name is null");} else {this.name = name;}}@ConstructorProperties({"t", "name", "age"})public XxxConstructorExample(T t, @NonNull String name, int age) {if (name == null) {throw new IllegalArgumentException("name is null");} else {this.t = t;this.name = name;this.age = age;}}
}
配置文件:
lombok.anyConstructor.suppressConstructorProperties = [true | false] (default: false)
设置为true时,生成的构造方法上将不会再出现@java.beans.ConstructorProperties注解。
lombok.[allArgsConstructor|requiredArgsConstructor|noArgsConstructor].flagUsage = [warning | error] (default: not set)
lombok.anyConstructor.flagUsage = [warning | error] (default: not set)
官方文档解释:
@xargsConstructor也可以用于枚举定义。生成的构造函数将始终是私有的,因为非私有构造函数在枚举中是不合法的。您不需要指定accesslevel.private。
当构造函数由@data、@value或任何其他lombok注释生成时,使用标记的配置键(flagUseage)不会触发。
(一) over~~