此枚举定义了两个值: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;
}
}