lombok无法对$前缀的字段进行代码生成
lombok作为一款java的代码辅助开发工具,在业界使用广泛,这里不讨论lombok的使用方法,只是写一下lombok的踩坑记录。
如题所示,lombok对于$前缀的字段是无法进行诸如get,set方法的生成的。估计可能会有同学会有疑问,字段的命名为什么要使用$作为前缀,这个我说一句估计大家都懂:前人挖坑后人填。好了,话不多说,具体的实例如下,Demo类使用lombok的Getter和Setter注解:
@Getter
@Setter
public class Demo {
private String name;
private String $type;
}
编译后生成的class文件:
public class Demo {
private String name;
private String $type;
public Demo() {
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
可以看到,$type字段并没有对应的get和set方法,我们再以@AllArgsConstructor和@EqualsAndHashCode注解进行测试:
@AllArgsConstructor
@EqualsAndHashCode
public class Demo {
private String name;
private String $type;
}
再次编译后生成的class文件:
public class Demo {
private String name;
private String $type;
public Demo(String name) {
this.name = name;
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Demo)) {
return false;
} else {
Demo other = (Demo)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;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof Demo;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $name = this.name;
int result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
}
可以看到equals方法中并没有对$type字段进行比较,而hashCode方法也没有使用$type字段参与计算,其他的诸如@NotNul,@ToString注解结果均一样。可能已经有同学发现在这两个方法里面,lombok生成的临时变量均是通过在字段前+$字符进行统一命名,我们可以推测,如果对$为前缀的字段进行处理,那么会与lombok的内部处理逻辑产生冲突。
对于这种$字段的处理其实就很简单了,那就是回归手动创建需要的方法。但是本人依然很好奇lombok到底是把这种字段过滤掉了,还是处理的时候发生错误了。于是就查看了下lombok源码,发现确实lombok在处理字段的过程中有对字段进行过滤,对于$为前缀的字段,都过滤掉了,不会参与后续的AST处理。
查看@Setter注解的主要处理类lombok.eclipse.handlers.HandleSetter,在主流程handle()方法中调用的generateSetterForType()方法里有这样一段代码:
if (EclipseHandlerUtil.filterField(fieldDecl) && (fieldDecl.modifiers & 16) == 0) {
this.generateSetterForField(field, (ASTNode)pos.get(), level);
}
这个EclipseHandlerUtil.filterField就是对字段进行过滤的地方,具体过滤逻辑如下:
public static boolean filterField(FieldDeclaration declaration) {
if (declaration.initialization instanceof AllocationExpression && ((AllocationExpression)declaration.initialization).enumConstant != null) {
return false;
} else if (declaration.type == null) {
return false;
} else if (declaration.name.length > 0 && declaration.name[0] == '$') {
return false;
} else {
return (declaration.modifiers & 8) == 0;
}
}
可以看到对于前缀是$的字段都被过滤了。但是具体为什么要过滤前缀是$的字段,即是什么原因导致lombok必须过滤掉这样的字段,这个在源码中本人没有查到,各位如果有谁知道的话,希望能在评论区留下您的灼见。最后,强烈建议大家在开发中一定要按照已有的规范进行开发,不然就会有千奇百怪的问题发生。