版权声明:可以任意转载,转载时请标明文章原始出处-xjtushilei和作者信息:石磊
前言
jdk10都已经支持var了,其实在很久之前lombok都已经基于Annotation Processing 技术(直接操纵抽象语法树AST,根据需要添加新节点)实现了更丰富的功能,使用起来还是很舒服的,但是由于其某些弊端,并没有流行起来。个人认为在vo特别复杂的情况下,代码量很大,修改很频繁下,使用lombok也不为过。如果在项目里未和队友商量的情况下,大量使用这种黑科技,就要被打死了。
原理
先来一波原理
自从Java 6起,javac就支持“JSR 269 Pluggable Annotation Processing API”规范,只要程序实现了该API,就能在javac运行的时候得到调用。
举例来说,现在有一个实现了”JSR 269 API”的程序A,那么使用javac编译源码的时候具体流程如下:
- javac对源代码进行分析,生成一棵抽象语法树(AST)
- 运行过程中调用实现了”JSR 269 API”的A程序
- 此时A程序就可以完成它自己的逻辑,包括修改第一步骤得到的抽象语法树(AST)
- javac使用修改后的抽象语法树(AST)生成字节码文件
IDEA使用准备
- 下载lombok插件,并安装
-
打开设置里默认关闭的Annotation Processing选项,方法如下图:
如果不打开改选项,则编译期会发生错误:
使用
val 和 var 动态类型
val和var的区别为:是否为final的。val是final的,但是var就是正常的变量。
//val
val example =new ArrayList<String>();
example.add("HelloWorld");
val foo = example.get(0);
System.out.println(foo.toLowerCase());
//val
val map = new HashMap<Integer, String>();
map.put(0, "zero");
map.put(5, "five");
for (val entry : map.entrySet()) {
System.out.printf("%d: %s\n", entry.getKey(), entry.getValue());
}
@NonNull 空指针变量
//@NonNull
class TestNull{
public void println(@NonNull String str){
System.out.println(str);
}
}
new TestNull().println("test pass");
new TestNull().println(null);
其功能相当于:
if (str == null) {
throw new NullPointerException("str");
}
@Cleanup 资源自动关闭
其实jdk7中已经实现了相关语法,这里提供了另一个语法。
首先jdk7里的 try-with-resource
,跟python里的语法差不多,都是自动关闭资源。有兴趣的可以自己查看。这里仅仅讲一下 lombok的实现。
// @Cleanup
@Cleanup OutputStream out = new FileOutputStream(new File("test.txt"));
out.write("HelloWorld!".getBytes());
相当于非JDK7的特殊语法情况下,最普通的处理方式:
OutputStream out = new FileOutputStream(new File("test.txt"));
try {
out.write("HelloWorld!".getBytes());
} finally {
if (out != null) {
out.close();
}
}
@Getter @Setter
这个很好理解,直接用就好啦。IDEA的快捷键的效果跟这个一样,会更朴实好用一些。
//@Getter @Setter
class TestGetterSetter {
@Getter
@Setter
private int age = 10;
}
val t = new TestGetterSetter();
t.setAge(25);
System.out.println(t.getAge());
@ToString
实现了 toString(),很好理解。
需要特别解释一些注释:
- includeFieldNames 是否显示字段名字
- exclude 排除哪些字段
- callSuper 是否将父类的成员加入到toString()
- of 跟 exclude 相对应,显示的增加自己想要显示的字段
//@ToString
@ToString(exclude="id",includeFieldNames=false)
class ToStringExample {
private static final int STATIC_VAR = 10;
private String name="名字";
private String[] tags={"1","2","3"};
private int id=1;
}
System.out.println(new ToStringExample());
EqualsAndHashCode
和toString的注释很相似,也是:
- exclude 排除哪些字段
- callSuper 是否将父类的成员加入到EqualsAndHashCode
- of 跟 exclude 相对应,显示的增加自己想要EqualsAndHashCode的字段
//EqualsAndHashCode
@EqualsAndHashCode(exclude={"id"})
class EqualsAndHashCodeExample {
private String name;
private int count;
private int id;
public EqualsAndHashCodeExample(String name, int count, int id) {
this.name = name;
this.count = count;
this.id = id;
}
}
val o1 = new EqualsAndHashCodeExample("name1", 12, 15);
val o2 = new EqualsAndHashCodeExample("name2", 12, 12);
val o3 = new EqualsAndHashCodeExample("name1", 12, 16);
System.out.println(o1.equals(o2));
System.out.println(o2.equals(o3));
System.out.println(o1.equals(o3));
构造函数
主要有三种, @NoArgsConstructor
, @RequiredArgsConstructo
, @AllArgsConstructor
。
其中主要解释一下sstaticName="of"
,效果相当于:
public static ConstructorExample of(int x, int y) {
return new ConstructorExample(int x, int y);
}
使用示例:
//AllArgsConstructor
@NoArgsConstructor
@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor(staticName = "of", access = AccessLevel.PROTECTED)
class ConstructorExample {
private int x, y;
}
val c1 = new ConstructorExample();
val c2 = new ConstructorExample(1, 2);
val c3 = ConstructorExample.of(1, 2);
@Data 五合一
A shortcut for @ToString, @EqualsAndHashCode, @Getter on all fields, @Setter on all non-final fields, and @RequiredArgsConstructor!
@Value 四合一
与@Data相对应的@Value, 两个annotation的主要区别就是如果变量不加@NonFinal ,@Value会给所有的弄成final的。当然如果是final的话,就没有set方法了。
@Builder
这个很好用!!builder模式用的很舒服。
@Builder
public class Example {
private int foo;
private final String bar;
}
//构造一个实例,属性不需要单独set
Example.builder().foo(1).bar(“test”).build()
log
@CommonsLog
Creates
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
@JBossLog
Creates
private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
@Log
Creates
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
@Log4j
Creates
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
@Log4j2
Creates
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
@Slf4j
Creates
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
@XSlf4j
Creates
private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
举例:
@Log4j
public class LogExample {
public static void main(String... args) {
log.error("Something's wrong here");
}
}
更多
请前去官网。
参考
- 官网 https://projectlombok.org/
- lombok的使用和原理 https://blog.csdn.net/dslztx/article/details/46715803