关于JAVA中源码级注解的编写及使用 (2)

​ 此枚举定义了两个值:UPPERCASE表示:大写;LOWERCASE表示:小写。
​ 2).修改"CheckWord"注解的代码:

@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.SOURCE) public @interface CheckWord { StartsWith value(); }

​ 说明:
​ a.StartsWith表示"数据类型",是一个"枚举"类型。
​ b.value表示"属性名",在使用此注解时,此属性的可取值只有StartsWith.UPPERCASE和StartsWith.LOWERCASE两个。
​ c.此属性没有设置"默认值",在使用此注解时必须要设置此属性的值。如下面的代码:
​ 3).修改"Student"类的代码:

@CheckWord(StartsWith.UPPERCASE) public class Student { @CheckWord(StartsWith.LOWERCASE) private String stuName; @CheckWord(StartsWith.LOWERCASE) public void show() { } } 2.4注解解析器:

​ 1."注解解析器"通常是随着注解一起定义的,用于解析"注解",并做一些事情。本例的"注解解析器"用于与javac编译器一起启动,编译Student类时,检查各元素的名称是否按要求以指定的大写、小写字母开头。
​ 2.自定义"注解解析器"需要继承AbstractProcessor类,并重写process()方法,完整的"注解解析器"代码如下:

import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; 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; @SupportedAnnotationTypes("CheckWord") @SupportedSourceVersion(SourceVersion.RELEASE_8) public class MyProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { //获取所有使用了@CheckWord注解的元素 Set<? extends Element> annoEle = roundEnv.getElementsAnnotatedWith(CheckWord.class); // 遍历这些元素 for (Element e : annoEle) { //获取元素名称,可能是:类名、属性名、方法名 String name = e.getSimpleName().toString(); //获取这个名字的第一个字母 char c = name.charAt(0); //获取这个元素上的@CheckWord注解对象 CheckWord anno = e.getAnnotation(CheckWord.class); //获取这个注解的value属性的值,它是一个StartsWith枚举类型 StartsWith sw = anno.value(); //判断属性值是否设置为:StartsWith.UPPERCASE,但名字的首字母是小写 if (sw == StartsWith.UPPERCASE && Character.isLowerCase(c)) { //向控制台打印异常信息 this.processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "名称:" + name + " 首字母应该大写!"); return false; } //判断属性值是否设置为:StartsWith.LOWERCASE,但名字的首字母是大写 if (sw == StartsWith.LOWERCASE && Character.isUpperCase(c)) { this.processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "名称:" + name + " 首字母应该小写!"); return false; } } return true; } }

​ 此代码的细节大家可以根据注释一点一点研究。一些类:TypeElement,RoundEnvironment,Element等的一些方法大家可以在API手册中查找。
​ 其它说明:
​ 1).@SupportedAnnotationTypes("CheckWord") : 表示只处理CheckWord注解。
​ @SupportedSourceVersion(SourceVersion.RELEASE_8) : 表示支持JDK1.8。

2.5.编译和测试:

1.在编译前,我们看一下完整的代码清单:请确保以下的四个类在同一个目录下
​ 1).枚举类:

public enum StartsWith { UPPERCASE, LOWERCASE }

​ 2).自定义注解类:

import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.SOURCE) public @interface CheckWord { StartsWith value(); }

​ 3).使用了CheckWord注解的Student类:

@CheckWord(StartsWith.UPPERCASE) public class Student { @CheckWord(StartsWith.LOWERCASE) private String StuName; @CheckWord(StartsWith.LOWERCASE) public void show() { } }

​ 4).注解解析器类:

import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; import java.util.Set; @SupportedAnnotationTypes("CheckWord") @SupportedSourceVersion(SourceVersion.RELEASE_8) public class MyProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { Set<? extends Element> annoEle = roundEnv.getElementsAnnotatedWith(CheckWord.class); for (Element e : annoEle) { String name = e.getSimpleName().toString(); char c = name.charAt(0); CheckWord anno = e.getAnnotation(CheckWord.class); StartsWith sw = anno.value(); if (sw == StartsWith.UPPERCASE) { if (Character.isLowerCase(c)) { this.processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "名称:" + name + " 首字母应该大写!"); return false; } } if (sw == StartsWith.LOWERCASE) { if (Character.isUpperCase(c)) { this.processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "名称:" + name + " 首字母应该小写!"); return false; } } } return true; } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyfypj.html