Lombok 是一种 Java™ 实用工具,它通过注释来帮助开发人员消除 Java 的冗长部分,尤其是简单的 Java 对象(POJO)。Lombok是如何消除Java中的冗长部分,可浏览《以简单的方式消除 Java 的冗长》。在这里,笔者只是介绍通过反编译由此生成的类文件,从中可看出 Lombok 工具都做了哪些事情。
1,编程时需要写的源文件(Lure.java)。我们假设 数据对象不想去写getter/setter等方法;color 属性是不需要包含在toString()、equals()、hashCode()方法中;而且 size 属性是只有包可见访问限制;以及operate()方法要求同步,且内部逻辑需要简化 try/finally语句样式。
正如我们看到的,所需要写的代码如下所示,非常简洁。
@ToString(exclude="color")
@EqualsAndHashCode(exclude="color")
@EqualsAndHashCode(exclude="color")
public @Data class Lure {
private String name;
private @Getter(AccessLevel.PACKAGE) int size;
private String color;
private String style;
private boolean active;
@Synchronized
public void operate(String[] args) throws IOException {
@Cleanup InputStream in = new FileInputStream(args[0]);
private String name;
private @Getter(AccessLevel.PACKAGE) int size;
private String color;
private String style;
private boolean active;
@Synchronized
public void operate(String[] args) throws IOException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
//write file code goes here
}
}
//write file code goes here
}
}
2,通过 javap 获得编译后的源文件(Lure.java)。显然,我们没有看到 @Synchronized 说起的作用。事实上,Lombok 是通过添加一个$lock对象来实现的,事实上,可以给 @Synchronized 添加参数的,比如@Synchronized("localock")。而有关toString()、equals()和hashCode()方法的实际情况,只有通过 JD 反编译其类文件后才查看得到(详见 3)。
D:\lombok\src\javac -cp lombok.jar Lure.java
D:\lombok\src\javap Lure
Compiled from "Lure.java"
public class Lure extends java.lang.Object{
public void operate(java.lang.String[]) throws java.io.IOException;
public java.lang.String toString();
public boolean equals(java.lang.Object);
public int hashCode();
public spike.lombok.Lure();
public java.lang.String getName();
public void setName(java.lang.String);
public void setSize(int);
public java.lang.String getColor();
public void setColor(java.lang.String);
public java.lang.String getStyle();
public void setStyle(java.lang.String);
public boolean isActive();
public void setActive(boolean);
int getSize();
}
Compiled from "Lure.java"
public class Lure extends java.lang.Object{
public void operate(java.lang.String[]) throws java.io.IOException;
public java.lang.String toString();
public boolean equals(java.lang.Object);
public int hashCode();
public spike.lombok.Lure();
public java.lang.String getName();
public void setName(java.lang.String);
public void setSize(int);
public java.lang.String getColor();
public void setColor(java.lang.String);
public java.lang.String getStyle();
public void setStyle(java.lang.String);
public boolean isActive();
public void setActive(boolean);
int getSize();
}
此外,通过 Eclipse IDE工具,可浏览到经 Lombok 注释编织代码后的代码树(Outline),见下图:
3,然后,试试通过 Java Decompiler 获得反编译后的源文件(Lure.java)内部方法的实现情况会如何。正如我们看到的,Lombok 做得非常棒。它把我们编程时应该写的代码全部编织好了。仅仅是通过少量的特定的注释类。
public class Lure {
private String name;
private int size;
private String color;
private String style;
private boolean active;
private final Object $lock; //因为@Synchronized注释
public Lure() {
this.$lock = new Object[0];//因为@Synchronized注释
}
public void operate(String[] args) throws IOException {
synchronized (this.$lock) {//因为@Synchronized注释
InputStream in = new FileInputStream(args[0]);
try {//因为 @Cleanup注释
OutputStream out = new FileOutputStream(args[1]);
out.close();
} finally {
in.close();//因为 @Cleanup注释
}
}
}
int getSize() { return this.size; }//包可见访问限制, @Getter(AccessLevel.PACKAGE)注释
public String toString() {//因为 @ToString(exclude="color")注释,见不到处理 color属性
return "Lure(name=" + this.name + ", size=" + this.size + ", style="
+ this.style + ", active=" + this.active + ")";
}
/*
* 因为@EqualsAndHashCode(exclude="color")注释,见不到处理 color属性
* 此方法包含反编译生成代码时的错误,如break label64,与Lombok编织代码无关
*/
public boolean equals(Object o) {
if (o == this) return true;
if (o == null) return false;
if (o.getClass() != super.getClass()) return false;
Lure other = (Lure) o;
if (this.name == null)
if (other.name == null) break label64;
else if (this.name.equals(other.name)) break label64;
return false;
if (this.size != other.size) label64: return false;
if (this.style == null)
if (other.style == null) break label110;
else if (this.style.equals(other.style)) break label110;
return false;
label110: return this.active == other.active;
}
/*
* 因为@EqualsAndHashCode(exclude="color")注释,见不到处理 color属性
* 存在反编译生成代码的情况,如 有 PRIME 的表达式,直接是 31, 与Lombok编织代码无关
*/
public int hashCode() {
int PRIME = 31;
int result = 1;
result = result * 31 + ((this.name == null) ? 0 : this.name.hashCode());
result = result * 31 + this.size;
result = result * 31 + ((this.style == null) ? 0 : this.style.hashCode());
return result * 31 + ((this.active) ? 1231 : 1237);
}
/*
* 因为 @Data注释,生成了随后的方法
*/
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
public void setSize(int size) { this.size = size; }
public String getColor() { return this.color; }
public void setColor(String color) { this.color = color; }
public String getStyle() { return this.style; }
public void setStyle(String style) { this.style = style; }
public boolean isActive() { return this.active; }
public void setActive(boolean active) { this.active = active; }
}
private String name;
private int size;
private String color;
private String style;
private boolean active;
private final Object $lock; //因为@Synchronized注释
public Lure() {
this.$lock = new Object[0];//因为@Synchronized注释
}
public void operate(String[] args) throws IOException {
synchronized (this.$lock) {//因为@Synchronized注释
InputStream in = new FileInputStream(args[0]);
try {//因为 @Cleanup注释
OutputStream out = new FileOutputStream(args[1]);
out.close();
} finally {
in.close();//因为 @Cleanup注释
}
}
}
int getSize() { return this.size; }//包可见访问限制, @Getter(AccessLevel.PACKAGE)注释
public String toString() {//因为 @ToString(exclude="color")注释,见不到处理 color属性
return "Lure(name=" + this.name + ", size=" + this.size + ", style="
+ this.style + ", active=" + this.active + ")";
}
/*
* 因为@EqualsAndHashCode(exclude="color")注释,见不到处理 color属性
* 此方法包含反编译生成代码时的错误,如break label64,与Lombok编织代码无关
*/
public boolean equals(Object o) {
if (o == this) return true;
if (o == null) return false;
if (o.getClass() != super.getClass()) return false;
Lure other = (Lure) o;
if (this.name == null)
if (other.name == null) break label64;
else if (this.name.equals(other.name)) break label64;
return false;
if (this.size != other.size) label64: return false;
if (this.style == null)
if (other.style == null) break label110;
else if (this.style.equals(other.style)) break label110;
return false;
label110: return this.active == other.active;
}
/*
* 因为@EqualsAndHashCode(exclude="color")注释,见不到处理 color属性
* 存在反编译生成代码的情况,如 有 PRIME 的表达式,直接是 31, 与Lombok编织代码无关
*/
public int hashCode() {
int PRIME = 31;
int result = 1;
result = result * 31 + ((this.name == null) ? 0 : this.name.hashCode());
result = result * 31 + this.size;
result = result * 31 + ((this.style == null) ? 0 : this.style.hashCode());
return result * 31 + ((this.active) ? 1231 : 1237);
}
/*
* 因为 @Data注释,生成了随后的方法
*/
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
public void setSize(int size) { this.size = size; }
public String getColor() { return this.color; }
public void setColor(String color) { this.color = color; }
public String getStyle() { return this.style; }
public void setStyle(String style) { this.style = style; }
public boolean isActive() { return this.active; }
public void setActive(boolean active) { this.active = active; }
}
小结
必须要说 Lombok 确是个小而精干的实用工具,但还有优化改进的地方,比如 @ToString、@EqualsAndHashCode等注释类的不包括(exclude)只允许单项。这意味着不需要(exclude)多项属性(field)时则不被允许。
转载于:https://blog.51cto.com/marchtiger/298029