java 机机接口定义_自定义Java里的注解处理器(二)

本篇主要介绍Java如何让在编译期间表示和处理代码。

APT

即为Annotation Processing Tool,它是javac的一个工具,中文意思为编译时注解处理器。APT可以用来在编译时扫描和处理注解。通过APT可以获取到注解和被注解对象的相关信息,在拿到这些信息后我们可以根据需求来自动的生成一些代码,省去了手动编写。注意,获取注解及生成代码都是在代码编译时候完成的,相比反射在运行时处理注解大大提高了程序性能。APT的核心是AbstractProcessor类,关于AbstractProcessor类后面会做详细说明。

Java自带的tools.jar包里面曾有com.sun.mirror.apt.*这样的包。从jdk1.8以后,所有的类都移到 javax.annotation.processing and javax.lang.model包中了。

Javax.lang.model包

这个包用来为 Java 编程语言建立模型的包的类和层次结构。 此包及其子包的成员适用于语言建模、语言处理任务和 API(包括但并不仅限于注释处理框架)。

此语言模型使用基于镜像(Morris) 的设计

实现声明,这个包及其子包你可以把它们当成编译时对Java代码的表示,在运行时获取Java类型信息有另一套规范,具体请参照java.lang.reflect包下的内容。

这个包下有三个类(含接口)

1.  UnknownEntityException该异常继承自RuntimeException,表示未知类型的实体遇到的异常的超类。如果语言有新的特性和新的结构类型出现,则这种情况可能会发生。访问者可能会抛出此异常的子类,以指示访问者是为该语言的先前版本创建的。

2.   SourceVersion

代表Java语言的版本信息,具体参阅对应版本Java版语言规范。

public enum SourceVersion {

/*

* Summary of language evolution

* 1.1: 类嵌套

* 1.2: 支持strictfp具体请参阅JLS 15.4

* 1.3: 没有变化

* 1.4: 断言

* 1.5: 注解,泛型,自动装箱,可变参数

* 1.6: 没有变化

* 1.7: diamond syntax, try-with-resources, etc.

* 1.8: lambda 表达式,默认方法     */

RELEASE_0,

RELEASE_1,

RELEASE_2,

RELEASE_3,

RELEASE_4,

RELEASE_5,

RELEASE_6,

RELEASE_7,

RELEASE_8;

}

3.AnnotatedConstruct

表示一个可以被注解的结构(元素),这个结构可以是元素和类型。具体描述请参阅JLS 9.6.6

这和类有几个重要的方法:

(1). List extends AnnotationMirror> getAnnotationMirrors();

这个方法返回直接声明在该元素上的注解,关于AnnotationMirror,在后面会有介绍。

(2)  A getAnnotation(Class annotationType);

返回指定类型所对应的注解,如果不存在,则返回null.

(3 ) A[] getAnnotationsByType(Class annotationType);

返回与该结构关联的注解. 与getAnnotation(Class)的区别在于,此方法检测其参数是否为可重复注解类型,如果是,则试图通过“looking through”来查找该类型的一个或多个容器注解。

Javax.lang.model.element包

1.AnnotationMirror接口 //代表一个注解.

(1)DeclaredType getAnnotationType();

返回该注解的类型.

(2)Map extends ExecutableElement, ? extends AnnotationValue> getElementValues();

反回该注解的元素值,这个值为由对应的元素和它对应的值组成的map. 包括那些在注解中显式设置值的元素,而不包括那些隐式的默认值的元素。如果想获取默认值的元素,使用Elements.getElementValuesWithDefaults()方法。Elements是一个工具类,提供了操作Element的方法。

2.Element

该接口继承自javax.lang.model.AnnotatedConstruct.该接口代表java程序中的元素,比如包,类,或者方法.每个元素表示静态、语言级别的结构(而不是虚拟机的运行时结构)。子类包括ExecutableElement, PackageElement, Parameterizable, QualifiedNameable,TypeElement, TypeParameterElement, VariableElement。

(1)TypeMirror asType()

返回TypeMirror,TypeMirror是元素的类型信息,包括包名,类(或方法,或参数)名/类型。TypeMirror的子类有ArrayType, DeclaredType, DisjunctiveType, ErrorType, ExecutableType, NoType, NullType, PrimitiveType, ReferenceType, TypeVariable, WildcardType ,getKind可以获取类型

(2)ElementKind getKind();

(3)Set getModifiers()

返回该元素的修饰符(包括注解),隐式修饰符也包含,比如接口方法中的public和static

(4)Element getEnclosingElement()

返回包围该元素的最内层的元素,即返回它的直接父元素。

* 如果这个元素的声明紧接在另一个元素的声明中,则返回另一个元素。

* 如果这是顶级类型,则返回其包。

* 如果这是一个包,则返回null。

* 如果这是类型参数,则返回类型参数的泛型元素。

* 如果这是一个方法或构造函数参数,则返回声明该参数的可执行元素。

(5)List extends Element> getEnclosedElements()

返回该元素的直接子元素。

(6) List extends AnnotationMirror> getAnnotationMirrors();

获得直接声明在该元素上的注解,如果要获得继承的注解,使用Eements#getAllAnnotationMirrors(Element)方法.

3.ElementKind

关于元素类型的枚举,主要包括:

PACKAGE 包

ENUM 枚举

CLASS 类

ANNOTATION_TYPE 注解

INTERFACE 接口

ENUM_CONSTANT 枚举常量

FIELD 字段

PARAMETER 方法参数

LOCAL_VARIABLE 局部变量

METHOD 方法

CONSTRUCTOR 构造方法

TYPE_PARAMETER 类型参数

STATIC_INIT 静态初始化块

INSTANCE_INIT 初始化块

如果我们要判断一个元素的类型,应该使用Element.getKind()方法配合ElementKind枚举类进行判断。避免使用instanceof进行判断,因为TypeElement既表示类又表示一个接口,这样判断的结果可能不是你想要的。

其他类型

TypeMirror

ypeMirror是一个接口,表示Java编程语言中的类型。这些类型包括基本类型、引用类型、数组类型、类型变量和null类型等,其子类如下:

ArrayType 表示数组类型

DeclaredType 表示声明类型(类或接口类型)

ErrorType 表示异常类或接口类型

ExecutableType 表示executable类型(方法、构造方法、初始化)

NoType 表示在实际类型不适合的地方使用的伪类型

NullType 表示null类型

PrimitiveType 表示基本数据类型

ReferenceType 表示引用类型

TypeVariable 表示类型变量

WildcardType 表示通配符类型参数。

TypeKind

定义了java中各种类型所对应的枚举。

BOOLEAN 基本类型boolean

INT 基本类型int

LONG 基本类型long

FLOAT 基本类型float

DOUBLE 基本类型double

VOID 对应于关键字void的伪类型

NULL null类型

ARRAY 数组类型

PACKAGE 对应于包元素的伪类型

EXECUTABLE 方法、构造方法、初始化

DECLARE 声明类型

我们想判断一个TypeMirror的类型,应该使用TypeMirror.getKind()方法配合TypeKind枚举类进行判断。避免使用instanceof进行判断,因为DeclaredType既表示类 (class) 类型又表示接口 (interface) 类型,这样判断的结果可能不是你想要的。

TypeMirror和 TypeKind有很大的区别:TypeKind仅仅是一个枚举类而已,方便你使用的;而TypeMirror是一个表示Java语言中类型的接口,你可与通过TypeMirror接口中的getKind()方法获取到一个TypeKind。TypeMirror的子类可以灵活的获取元素的属性,例如它的 ExecutableType 子类(表示executable类型(方法、构造方法、初始化))。可以通过它的getReturnType获取方法的返回值类型(返回值也是一个TypeMirror),通过getParameterTypes()获取方法的参数(返回值是一个List extends TypeMirror>)。

至于为什么要介绍这么多内容,是因为上面这些包是可以用来处理注解的工具,注解处理器是运行在它自己的JVM中。javac启动一个完整Java虚拟机来运行注解处理器,这意味着你可以使用任何你在其他java应用中使用的的东西。javac这个命令实现了javax.lang.model中的API。

下一篇,你将学会使用AbstractProcessor自定义自己的注解处理器,并将它注册到javac中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值