lombok用法

news/2024/7/3 0:18:21

一、lombok介绍

官方定义:

Project Lombok is a java library that automatically plugs into your editor and build 
tools, spicing up your java.Never write another getter or equals method again, 
with one annotation your class has a fully featured builder, Automate your logging 
variables, and much more.

Lombok是一个Java库,能自动插入编辑器并构建工具,简化Java开发。通过添加注解的方式,不需要为类编写getter或eques方法,同时可以自动化日志变量

lombok是用java语言开发的一个插件,通过自定义注解来达到简化java代码的一个类库

Lombok 能够在编译源代码期间自动帮我们生成这些方法(get/set/equals等),但并不会像反射那样降低程序的性能。

二、lombok的使用

1.在pom.xml中加入依赖

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.4</version><scope>provided</scope>
</dependency>

2.安装lombok插件

2.1 IDEA安装方式

File=>settings

安装好后重启,然后点击项目maven update,不行的话多执行几次

2.2 eclipse安装方式

下载lombok.jar包放到eclipse安装目录,再eclipse.ini配置后面加入以下内容:

-javaagent:lombok.jar
-vmargs -javaagent:lombok.jar

安装好后重启,然后点击项目maven update,不行的话多执行几次

三、lombok常用的注解

1.1 @Getter and @Setter

@Getter 或 @Setter 注解作用在类或字段上,Lombok 会自动生成默认的 getter/setter 方法

  • @Getter 注解
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface Getter {// 若getter方法非public的话,可以设置可访问级别lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;AnyAnnotation[] onMethod() default {};// 是否启用延迟初始化boolean lazy() default false;
}
  • @Setter
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface Setter {// 若setter方法非public的话,可以设置可访问级别lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;AnyAnnotation[] onMethod() default {};AnyAnnotation[] onParam() default {};
}

使用示例

@Getter
@Setter
public class GetterAndSetterDemo {String firstName;String lastName;LocalDate dateOfBirth;
}

以上代码经过 Lombok 编译后,会生成如下代码:

public class GetterAndSetterDemo {String firstName;String lastName;LocalDate dateOfBirth;public GetterAndSetterDemo() {}// 省略其它setter和getter方法public String getFirstName() {return this.firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}
}

1.2 @NoArgsConstructor

@NoArgsConstructor 注解可以为指定类,生成默认的构造函数

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface NoArgsConstructor {// 若设置该属性,将会生成一个私有的构造函数且生成一个staticName指定的静态方法String staticName() default "";AnyAnnotation[] onConstructor() default {};// 设置生成构造函数的访问级别,默认是publicAccessLevel access() default lombok.AccessLevel.PUBLIC;// 若设置为true,则初始化所有final的字段为0/null/falseboolean force() default false;
}

使用示例

@NoArgsConstructor(staticName = "getInstance")
public class NoArgsConstructorDemo {private long id;private String name;private int age;
}

以上代码经过 Lombok 编译后,会生成如下代码:

public class NoArgsConstructorDemo {private long id;private String name;private int age;private NoArgsConstructorDemo() {}public static NoArgsConstructorDemo getInstance() {return new NoArgsConstructorDemo();}
}

1.3 @AllArgsConstructor

使用 @AllArgsConstructor 注解可以为指定类,生成包含所有成员的构造函数,@AllArgsConstructor 注解的定义如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface AllArgsConstructor {// 若设置该属性,将会生成一个私有的构造函数且生成一个staticName指定的静态方法String staticName() default "";AnyAnnotation[] onConstructor() default {};// 设置生成构造函数的访问级别,默认是publicAccessLevel access() default lombok.AccessLevel.PUBLIC;
}

使用示例

@AllArgsConstructor
public class AllArgsConstructorDemo {private long id;private String name;private int age;
}

以上代码经过 Lombok 编译后,会生成如下代码:

public class AllArgsConstructorDemo {private long id;private String name;private int age;public AllArgsConstructorDemo(long id, String name, int age) {this.id = id;this.name = name;this.age = age;}
}

1.4 @RequiredArgsConstructor

使用 @RequiredArgsConstructor 注解可以为指定类必需初始化的成员变量,如 final 成员变量,生成对应的构造函数,@RequiredArgsConstructor 注解的定义如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface RequiredArgsConstructor {// 若设置该属性,将会生成一个私有的构造函数且生成一个staticName指定的静态方法String staticName() default "";AnyAnnotation[] onConstructor() default {};// 设置生成构造函数的访问级别,默认是publicAccessLevel access() default lombok.AccessLevel.PUBLIC;
}

使用示例

@RequiredArgsConstructor
public class RequiredArgsConstructorDemo {private final long id;private String name;private int age;
}

以上代码经过 Lombok 编译后,会生成如下代码:

public class RequiredArgsConstructorDemo {private final long id;private String name;private int age;public RequiredArgsConstructorDemo(long id) {this.id = id;}
}

1.5 @EqualsAndHashCode

使用 @EqualsAndHashCode 注解可以为指定类生成 equals 和 hashCode 方法, @EqualsAndHashCode 注解的定义如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface EqualsAndHashCode {// 指定在生成的equals和hashCode方法中需要排除的字段列表String[] exclude() default {};// 显式列出用于identity的字段,一般情况下non-static,non-transient字段会被用于identityString[] of() default {};// 标识在执行字段计算前,是否调用父类的equals和hashCode方法boolean callSuper() default false;boolean doNotUseGetters() default false;AnyAnnotation[] onParam() default {};@Deprecated@Retention(RetentionPolicy.SOURCE)@Target({})@interface AnyAnnotation {}@Target(ElementType.FIELD)@Retention(RetentionPolicy.SOURCE)public @interface Exclude {}@Target({ElementType.FIELD, ElementType.METHOD})@Retention(RetentionPolicy.SOURCE)public @interface Include {String replaces() default "";}
}

使用示例

@EqualsAndHashCode
public class EqualsAndHashCodeDemo {String firstName;String lastName;LocalDate dateOfBirth;
}

以上代码经过 Lombok 编译后,会生成如下代码:

public class EqualsAndHashCodeDemo {String firstName;String lastName;LocalDate dateOfBirth;public EqualsAndHashCodeDemo() {}public boolean equals(Object o) {if (o == this) {return true;} else if (!(o instanceof EqualsAndHashCodeDemo)) {return false;} else {EqualsAndHashCodeDemo other = (EqualsAndHashCodeDemo)o;if (!other.canEqual(this)) {return false;} else {// 已省略大量代码}}public int hashCode() {int PRIME = true;int result = 1;Object $firstName = this.firstName;int result = result * 59 + ($firstName == null ? 43 : $firstName.hashCode());Object $lastName = this.lastName;result = result * 59 + ($lastName == null ? 43 : $lastName.hashCode());Object $dateOfBirth = this.dateOfBirth;result = result * 59 + ($dateOfBirth == null ? 43 : $dateOfBirth.hashCode());return result;}
}

1.6 @ToString

使用 @ToString 注解可以为指定类生成 toString 方法, @ToString 注解的定义如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface ToString {// 打印输出时是否包含字段的名称boolean includeFieldNames() default true;// 列出打印输出时,需要排除的字段列表String[] exclude() default {};// 显式的列出需要打印输出的字段列表String[] of() default {};// 打印输出的结果中是否包含父类的toString方法的返回结果boolean callSuper() default false;boolean doNotUseGetters() default false;boolean onlyExplicitlyIncluded() default false;@Target(ElementType.FIELD)@Retention(RetentionPolicy.SOURCE)public @interface Exclude {}@Target({ElementType.FIELD, ElementType.METHOD})@Retention(RetentionPolicy.SOURCE)public @interface Include {int rank() default 0;String name() default "";}
}

使用示例

@ToString(exclude = {"dateOfBirth"})
public class ToStringDemo {String firstName;String lastName;LocalDate dateOfBirth;
}

以上代码经过 Lombok 编译后,会生成如下代码:

public class ToStringDemo {String firstName;String lastName;LocalDate dateOfBirth;public ToStringDemo() {}public String toString() {return "ToStringDemo(firstName=" + this.firstName + ", lastName=" +this.lastName + ")";}
}

1.7 @Data

@Data 注解与同时使用以下的注解的效果是一样的:

  1. @ToString
  2. @Getter
  3. @Setter
  4. @RequiredArgsConstructor
  5. @EqualsAndHashCode

@Data 注解的定义如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Data {String staticConstructor() default "";
}

使用示例

@Data
public class DataDemo {private Long id;private String summary;private String description;
}

以上代码经过 Lombok 编译后,会生成如下代码:

public class DataDemo {private Long id;private String summary;private String description;public DataDemo() {}// 省略summary和description成员属性的setter和getter方法public Long getId() {return this.id;}public void setId(Long id) {this.id = id;}public boolean equals(Object o) {if (o == this) {return true;} else if (!(o instanceof DataDemo)) {return false;} else {DataDemo other = (DataDemo)o;if (!other.canEqual(this)) {return false;} else {// 已省略大量代码}}}protected boolean canEqual(Object other) {return other instanceof DataDemo;}public int hashCode() {int PRIME = true;int result = 1;Object $id = this.getId();int result = result * 59 + ($id == null ? 43 : $id.hashCode());Object $summary = this.getSummary();result = result * 59 + ($summary == null ? 43 : $summary.hashCode());Object $description = this.getDescription();result = result * 59 + ($description == null ? 43 : $description.hashCode());return result;}public String toString() {return "DataDemo(id=" + this.getId() + ", summary=" + this.getSummary() + ", description=" + this.getDescription() + ")";}
}

1.8 @Log

若你将 @Log 的变体放在类上(适用于你所使用的日志记录系统的任何一种);之后,你将拥有一个静态的 final log 字段,然后你就可以使用该字段来输出日志。

1.9 @Synchronized

@Synchronized 是同步方法修饰符的更安全的变体。与 synchronized 一样,该注解只能应用在静态和实例方法上。它的操作类似于 synchronized 关键字,但是它锁定在不同的对象上。synchronized 关键字应用在实例方法时,锁定的是 this 对象,而应用在静态方法上锁定的是类对象。@Synchronized 注解的定义如下:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Synchronized {// 指定锁定的字段名称String value() default "";
}

使用示例:

public class SynchronizedDemo {private final Object readLock = new Object();@Synchronizedpublic static void hello() {System.out.println("world");}@Synchronizedpublic int answerToLife() {return 42;}@Synchronized("readLock")public void foo() {System.out.println("bar");}
}

以上代码经过 Lombok 编译后,会生成如下代码:

public class SynchronizedDemo {private static final Object $LOCK = new Object[0];private final Object $lock = new Object[0];private final Object readLock = new Object();public SynchronizedDemo() {}public static void hello() {synchronized($LOCK) {System.out.println("world");}}public int answerToLife() {synchronized(this.$lock) {return 42;}}public void foo() {synchronized(this.readLock) {System.out.println("bar");}}
}

1.10 @Builder

使用 @Builder 注解可以为指定类实现建造者模式,该注解可以放在类、构造函数或方法上。@Builder 注解的定义如下:

@Target({TYPE, METHOD, CONSTRUCTOR})
@Retention(SOURCE)
public @interface Builder {@Target(FIELD)@Retention(SOURCE)public @interface Default {}// 创建新的builder实例的方法名称String builderMethodName() default "builder";// 创建Builder注解类对应实例的方法名称String buildMethodName() default "build";// builder类的名称String builderClassName() default "";boolean toBuilder() default false;AccessLevel access() default lombok.AccessLevel.PUBLIC;@Target({FIELD, PARAMETER})@Retention(SOURCE)public @interface ObtainVia {String field() default "";String method() default "";boolean isStatic() default false;}
}

使用示例

@Builder
public class BuilderDemo {private final String firstname;private final String lastname;private final String email;
}

以上代码经过 Lombok 编译后,会生成如下代码:

public class BuilderDemo {private final String firstname;private final String lastname;private final String email;BuilderDemo(String firstname, String lastname, String email) {this.firstname = firstname;this.lastname = lastname;this.email = email;}public static BuilderDemo.BuilderDemoBuilder builder() {return new BuilderDemo.BuilderDemoBuilder();}public static class BuilderDemoBuilder {private String firstname;private String lastname;private String email;BuilderDemoBuilder() {}public BuilderDemo.BuilderDemoBuilder firstname(String firstname) {this.firstname = firstname;return this;}public BuilderDemo.BuilderDemoBuilder lastname(String lastname) {this.lastname = lastname;return this;}public BuilderDemo.BuilderDemoBuilder email(String email) {this.email = email;return this;}public BuilderDemo build() {return new BuilderDemo(this.firstname, this.lastname, this.email);}public String toString() {return "BuilderDemo.BuilderDemoBuilder(firstname=" + this.firstname + ", lastname=" + this.lastname + ", email=" + this.email + ")";}}
}

1.11 @SneakyThrows

@SneakyThrows 注解用于自动抛出已检查的异常,而无需在方法中使用 throw 语句显式抛出。@SneakyThrows 注解的定义如下:

@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.SOURCE)
public @interface SneakyThrows {// 设置你希望向上抛的异常类Class<? extends Throwable>[] value() default java.lang.Throwable.class;
}

使用示例

public class SneakyThrowsDemo {@SneakyThrows@Overrideprotected Object clone() {return super.clone();}
}

以上代码经过 Lombok 编译后,会生成如下代码:

public class SneakyThrowsDemo {public SneakyThrowsDemo() {}protected Object clone() {try {return super.clone();} catch (Throwable var2) {throw var2;}}
}

1.12 @NonNull

你可以在方法或构造函数的参数上使用 @NonNull 注解,它将会为你自动生成非空校验语句。@NonNull 注解的定义如下:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
@Retention(RetentionPolicy.CLASS)
@Documented
public @interface NonNull {
}

使用示例

public class NonNullDemo {@Getter@Setter@NonNullprivate String name;
}

以上代码经过 Lombok 编译后,会生成如下代码:

public class NonNullDemo {@NonNullprivate String name;public NonNullDemo() {}@NonNullpublic String getName() {return this.name;}public void setName(@NonNull String name) {if (name == null) {throw new NullPointerException("name is marked non-null but is null");} else {this.name = name;}}
}

1.13 @Clean

@Clean 注解用于自动管理资源,用在局部变量之前,在当前变量范围内即将执行完毕退出之前会自动清理资源,自动生成 try-finally 这样的代码来关闭流。

@Target(ElementType.LOCAL_VARIABLE)
@Retention(RetentionPolicy.SOURCE)
public @interface Cleanup {// 设置用于执行资源清理/回收的方法名称,对应方法不能包含任何参数,默认名称为close。String value() default "close";
}


使用示例:

public class CleanupDemo {public static void main(String[] args) throws IOException {@Cleanup InputStream in = new FileInputStream(args[0]);@Cleanup OutputStream out = new FileOutputStream(args[1]);byte[] b = new byte[10000];while (true) {int r = in.read(b);if (r == -1) break;out.write(b, 0, r);}}
}

以上代码经过 Lombok 编译后,会生成如下代码:

public class CleanupDemo {public CleanupDemo() {}public static void main(String[] args) throws IOException {FileInputStream in = new FileInputStream(args[0]);try {FileOutputStream out = new FileOutputStream(args[1]);try {byte[] b = new byte[10000];while(true) {int r = in.read(b);if (r == -1) {return;}out.write(b, 0, r);}} finally {if (Collections.singletonList(out).get(0) != null) {out.close();}}} finally {if (Collections.singletonList(in).get(0) != null) {in.close();}}}
}

1.14 @With

在类的字段上应用 @With 注解之后,将会自动生成一个 withFieldName(newValue) 的方法,该方法会基于 newValue 调用相应构造函数,创建一个当前类对应的实例。@With 注解的定义如下:

@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface With {AccessLevel value() default AccessLevel.PUBLIC;With.AnyAnnotation[] onMethod() default {};With.AnyAnnotation[] onParam() default {};@Deprecated@Retention(RetentionPolicy.SOURCE)@Target({})public @interface AnyAnnotation {}
}

使用示例

public class WithDemo {@With(AccessLevel.PROTECTED)@NonNullprivate final String name;@Withprivate final int age;public WithDemo(String name, int age) {if (name == null) throw new NullPointerException();this.name = name;this.age = age;}
}

以上代码经过 Lombok 编译后,会生成如下代码:

public class WithDemo {@NonNullprivate final String name;private final int age;public WithDemo(String name, int age) {if (name == null) {throw new NullPointerException();} else {this.name = name;this.age = age;}}protected WithDemo withName(@NonNull String name) {if (name == null) {throw new NullPointerException("name is marked non-null but is null");} else {return this.name == name ? this : new WithDemo(name, this.age);}}public WithDemo withAge(int age) {return this.age == age ? this : new WithDemo(this.name, age);}
}

四、lombok工作原理

核心之处就是对于注解的解析上。JDK5引入了注解的同时,也提供了两种解析方式。

  • 运行时解析

运行时能够解析的注解,必须将@Retention设置为RUNTIME,这样就可以通过反射拿到该注解。java.lang.reflect反射包中提供了一个接口AnnotatedElement,该接口定义了获取注解信息的几个方法,Class、Constructor、Field、Method、Package等都实现了该接口,对反射熟悉的朋友应该都会很熟悉这种解析方式。

  • 编译时解析

编译时解析有两种机制,分别简单描述下:

1)Annotation Processing Tool

apt自JDK5产生,JDK7已标记为过期,不推荐使用,JDK8中已彻底删除,自JDK6开始,可以使用Pluggable Annotation Processing API来替换它,apt被替换主要有2点原因:

  • api都在com.sun.mirror非标准包下
  • 没有集成到javac中,需要额外运行

2)Pluggable Annotation Processing API

JSR 269自JDK6加入,作为apt的替代方案,它解决了apt的两个问题,javac在执行的时候会调用实现了该API的程序,这样我们就可以对编译器做一些增强,javac执行的过程如下:

lombok工作原理

Lombok本质上就是一个实现了“JSR 269 API”的程序。在使用javac的过程中,它产生作用的具体流程如下:

  1. javac对源代码进行分析,生成了一棵抽象语法树(AST)
  2. 运行过程中调用实现了“JSR 269 API”的Lombok程序
  3. 此时Lombok就对第一步骤得到的AST进行处理,找到@Data注解所在类对应的语法树(AST),然后修改该语法树(AST),增加getter和setter方法定义的相应树节点
  4. javac使用修改后的抽象语法树(AST)生成字节码文件,即给class增加新的节点(代码块)

jsr269抽象语法树操作API编译期注解处理-简单demo

JDK1.6引入了JSR269规范,允许在编译期处理注解,读取、修改、添加抽象语法树中的内容。
lombok插件就是应用了这个

1.自定义注解

package com.xiao.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定义Data注解** @author xiaoss* @since 1.0, 2022年05月09日 09:43:44*/
@Target({ElementType.TYPE})   //标识作用对象
@Retention(RetentionPolicy.SOURCE)
/*
注解保留策略类:
1)RetentionPolicy.SOURCE表示该注解只在源码中保留,编译之后class文件就不存在了
2)RetentionPolicy.CLASS表示该注解只保留到编译后,运行时候会被遗弃(如:在运行时通过反射去获取这个注解是找不到的)
3)RetentionPolicy.RUNTIME 表示该注解一直保留到运行
*/
public @interface CustomData {
}

2.创建处理器

package com.xiao.annotation;import com.google.auto.service.AutoService;
import com.sun.source.tree.Tree;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.tree.TreeTranslator;
import com.sun.tools.javac.util.*;import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import java.util.Set;/*** 自定义注解处理类,继承AbstractProcessor,重写init和process方法** @author xiaoss* @since 1.0, 2022年05月09日 10:05:59*/
@AutoService(Processor.class)
@SupportedAnnotationTypes("com.xiao.annotation.CustomData")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class CustomDataAnnotationProcessor extends AbstractProcessor {private JavacTrees javacTrees;private TreeMaker treeMaker;private Names names;private Messager messager;/*** 从Context中初始化JavacTrees,TreeMaker,Names* @param processingEnv*/@Overridepublic synchronized void init(ProcessingEnvironment processingEnv) {messager.printMessage(Diagnostic.Kind.ERROR,"========================>init");super.init(processingEnv);Context context = ((JavacProcessingEnvironment) processingEnv).getContext();javacTrees = JavacTrees.instance(processingEnv);treeMaker = TreeMaker.instance(context);names = Names.instance(context);}@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {messager.printMessage(Diagnostic.Kind.ERROR,"========================>process");messager.printMessage(Diagnostic.Kind.NOTE, "source version -- " + getSupportedSourceVersion());// 获取注解类的集合,之后依次去处理Set<? extends Element> set = roundEnv.getElementsAnnotatedWith(CustomData.class);for (Element element : set) {// 获取当前类的抽象语法树JCTree tree = javacTrees.getTree(element);// 获取抽象语法树的所有节点// Visitor 抽象内部类,内部定义了访问各种语法节点的方法tree.accept(new TreeTranslator() {@Overridepublic void visitClassDef(JCTree.JCClassDecl jcClassDecl) {jcClassDecl.defs.stream()// 过滤,只处理变量类型.filter(it -> it.getKind().equals(Tree.Kind.VARIABLE))// 类型强转.map(it -> (JCTree.JCVariableDecl) it).forEach(it -> {System.out.println(it.toString());// 添加get方法jcClassDecl.defs = jcClassDecl.defs.prepend(genGetterMethod(it));// 添加set方法jcClassDecl.defs = jcClassDecl.defs.prepend(genSetterMethod(it));});super.visitClassDef(jcClassDecl);}});}return true;}/*** 生成get方法* @param jcVariableDecl* @return*/private JCTree.JCMethodDecl genGetterMethod(JCTree.JCVariableDecl jcVariableDecl) {// 生成return语句,return this.xxxJCTree.JCReturn returnStatement = treeMaker.Return(treeMaker.Select(treeMaker.Ident(names.fromString("this")),jcVariableDecl.getName()));ListBuffer<JCTree.JCStatement> statements = new ListBuffer<JCTree.JCStatement>().append(returnStatement);// public 方法访问级别修饰JCTree.JCModifiers modifiers = treeMaker.Modifiers(Flags.PUBLIC);// 方法名 getXXX ,根据字段名生成首字母大写的get方法Name getMethodName = createGetMethodName(jcVariableDecl.getName());// 返回值类型,get类型的返回值类型与字段类型一致JCTree.JCExpression returnMethodType = jcVariableDecl.vartype;// 生成方法体JCTree.JCBlock body = treeMaker.Block(0, statements.toList());// 泛型参数列表List<JCTree.JCTypeParameter> methodGenericParamList = List.nil();// 参数值列表List<JCTree.JCVariableDecl> parameterList = List.nil();// 异常抛出列表List<JCTree.JCExpression> throwCauseList = List.nil();// 生成方法定义树节点return treeMaker.MethodDef(// 方法访问级别修饰符modifiers,// get 方法名getMethodName,// 返回值类型returnMethodType,// 泛型参数列表methodGenericParamList,//参数值列表parameterList,// 异常抛出列表throwCauseList,// 方法默认体body,// 默认值null);}/*** 生成set方法* @param jcVariableDecl* @return*/private JCTree.JCMethodDecl genSetterMethod(JCTree.JCVariableDecl jcVariableDecl) {// this.xxx=xxxJCTree.JCExpressionStatement statement = treeMaker.Exec(treeMaker.Assign(treeMaker.Select(treeMaker.Ident(names.fromString("this")),jcVariableDecl.getName()),treeMaker.Ident(jcVariableDecl.getName())));ListBuffer<JCTree.JCStatement> statements = new ListBuffer<JCTree.JCStatement>().append(statement);// set方法参数JCTree.JCVariableDecl param = treeMaker.VarDef(// 访问修饰符treeMaker.Modifiers(Flags.PARAMETER, List.nil()),// 变量名jcVariableDecl.name,//变量类型jcVariableDecl.vartype,// 变量初始值null);// 方法访问修饰符 publicJCTree.JCModifiers modifiers = treeMaker.Modifiers(Flags.PUBLIC);// 方法名(setXxx),根据字段名生成首选字母大写的set方法Name setMethodName = createSetMethodName(jcVariableDecl.getName());// 返回值类型voidJCTree.JCExpression returnMethodType = treeMaker.Type(new Type.JCVoidType());// 生成方法体JCTree.JCBlock body = treeMaker.Block(0, statements.toList());// 泛型参数列表List<JCTree.JCTypeParameter> methodGenericParamList = List.nil();// 参数值列表List<JCTree.JCVariableDecl> parameterList = List.of(param);// 异常抛出列表List<JCTree.JCExpression> throwCauseList = List.nil();// 生成方法定义语法树节点return treeMaker.MethodDef(// 方法级别访问修饰符modifiers,// set 方法名setMethodName,// 返回值类型returnMethodType,// 泛型参数列表methodGenericParamList,// 参数值列表parameterList,// 异常抛出列表throwCauseList,// 方法体body,// 默认值null);}/*** 生成get方法名称* @param variableName* @return*/private Name createGetMethodName(Name variableName) {String fieldName = variableName.toString();return names.fromString("get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1));}/*** 生成set方法名称* @param variableName* @return*/private Name createSetMethodName(Name variableName) {String fieldName = variableName.toString();System.out.println(fieldName.substring(1));return names.fromString("set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1));}}

3.pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.xiao</groupId><artifactId>custom-annotation</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><java.home>D:\java\jdk1.8\</java.home></properties><dependencies><dependency><groupId>com.google.auto.service</groupId><artifactId>auto-service</artifactId><version>1.0</version></dependency><dependency><groupId>jdk.tools</groupId><artifactId>jdk.tools</artifactId><version>1.8</version><scope>system</scope><systemPath>${java.home}/lib/tools.jar</systemPath></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration><executions><execution><id>default-compile</id><configuration><compilerArgument>-proc:none</compilerArgument><source>1.8</source><target>1.8</target></configuration></execution></executions></plugin></plugins></build></project>

五、lombok优缺点

优点:

  1. 能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,提高了一定的开发效率
  2. 让代码变得简洁,不用过多的去关注相应的方法
  3. 属性做修改时,也简化了维护为这些属性所生成的getter/setter方法等

缺点:

  1. 不支持多种参数构造器的重载
  2. 虽然省去了手动创建getter/setter方法的麻烦,但大大降低了源代码的可读性和完整性,降低了阅读源代码的舒适度

 


http://lihuaxi.xjx100.cn/news/244082.html

相关文章

ubuntu 14.04 下通过apt-get 安装jdk

为什么80%的码农都做不了架构师&#xff1f;>>> Installing default JRE/JDK sudo apt-get update sudo apt-get install default-jre sudo apt-get install default-jdk Installing Oracle JDK sudo apt-get install python-software-properties sudo add-apt-rep…

side menu待研究

2019独角兽企业重金招聘Python工程师标准>>> http://fontawesome.bootstrapcheatsheets.com/ http://www.queness.com/post/14666/recreate-google-nexus-menu http://www.jqueryscript.net/demo/Sliding-Side-Menu-Panel-with-jQuery-Bootstrap-BootSideMenu/ &a…

【TCP/IP协议 卷一:协议】第三章 IP:网际协议

3.1 引言 unreliable不可靠的意思是它并不能保证IP数据报能成功的到达目的地。IP只提供尽力而为的传输服务。conectionless无连接的意思是IP并不维护任何关于后续数据报的状态信息。整个数据报的处理是相互独立的。即每个数据报都是独立地进行路由选择&#xff0c;可能选择不同…

遍历Map的四种方法

2019独角兽企业重金招聘Python工程师标准>>> public static void main(String[] args) { Map<String, String> map new HashMap<String, String>(); map.put("1", "value1"); map.put("2", "value2"); map…

WPS 2019 更新版(8392)发布,搭配优麒麟 19.04 运行更奇妙!

WPS 2019 支持全新的外观界面、目录更新、方框打勾、智能填充、内置浏览器、窗口拆组、个人中心等功能。特别是全新的新建页面&#xff0c;让你可以整合最近打开的文档、本地模版、公文模版、在线模板等。 随着优麒麟即将发布的新版 19.04 的到来&#xff0c;金山办公软件也带来…

java对图片按照指定尺寸压缩

1.pom.xml引入依赖 <dependency><groupId>net.coobird</groupId><artifactId>thumbnailator</artifactId><version>0.4.8</version></dependency> 2.接口 /*** 上传人员头像* param multipartFile* return*/Log(title &qu…

Linux man命令

【功能说明】&#xff1a;详细记录着命令或文件的操作说明&#xff08;manual&#xff09;【语法格式】&#xff1a;man [命令|文件名]【实践操作】&#xff1a;man ls常用代号说明代号 代表内容1User Commands&#xff08;一般用户可使用的命令&#xff1a;ls&#xff09;4Lin…

runtime实践之Method Swizzling

利用 Objective-C 的 Runtime 特性&#xff0c;我们可以给语言做扩展&#xff0c;帮助解决项目开发中的一些设计和技术问题。这一篇&#xff0c;我们来探索一些利用 Objective-C Runtime 的黑色技巧。这些技巧中最具争议的或许就是 Method Swizzling 。 介绍一个技巧&#xff0…