本篇博文来自《深入理解Java虚拟机--JVM高级特性与最佳实践》本书。 使用注释处理器API创建具有自己编码样式的代码验证工具NameCheckProcessor。
java程序命名约定必须遵守以下格式的书写规则:
第1类或接口:符合驼鸟式命名法,首字母大写
2方法:符合骆驼式命名法,首字母小写
3个字段
1 )类或实例变量:符合驼峰式命名法,首字母小写
2 )常量)必须全部由大写字母或下划线组成,且第一个字符不得为下划线
代码实现:
注释处理器: NameCheckProcessor
import java.util.Set;
导入javax.annotation.processing.abstract processor;
导入javax.annotation.processing.processing environment;
import javax.annotation.processing.round environment;
import javax.annotation.processing.supportedannotationtypes;
import javax.annotation.processing.supportedsourceversion;
导入javax.lang.model.source version;
import javax.lang.model.element.element;
import javax.lang.model.element.type element;
//*
*
* @ author管理员
*
*/
//所有注释都可以由“*”支持
@supportedannotationtypes('* ' )
仅支持//1.6的java代码
@ supportedsourceversion (source version.release _6)。
publicclassnamecheckprocessorextendsabstractprocessor {
私有名称检查器名称检查器;
//*
*初始化名称检查插件
*/
@Override
publicsynchronizedvoidinit (processingenvironmentprocessingenv ) {
sper.init (处理env );
name checker=newname checker (处理env );
}
//*
*检查输入的语法树中每个节点的名称
*/
@Override
publicbooleanprocess (setextendstypeelementannotations,循环环境循环env ) {
if (! roundEnv.processingOver (
for (elementelement : round env.getrootelements () ) )
namechecker.checknames(element;
}
}
返回假;
}
}
命名检查器: NameChecker
import java.util.EnumSet;
import javax.annotation.processing.messager;
导入javax.annotation.processing.processing environment;
import javax.lang.model.element.element;
import javax.lang.model.element.element kind;
导入javax.lang.model.element.executable element;
import javax.lang.model.element.modifier;
import javax.lang.model.element.name;
import javax.lang.model.element.type element;
导入javax.lang.model.element.variable element;
import javax.lang.model.util.El
ementScanner6;import javax.tools.Diagnostic.Kind;
/**
* 程序名称规范的编译器插件 如果程序名称不符合规范,则输出一个编译器的WARNING信息
*
* @author Administrator
*
*/
public class NameChecker {
private final Messager messager;
NameCheckScanner nameCheckScanner = new NameCheckScanner();
public NameChecker(ProcessingEnvironment processingEnv) {
this.messager = processingEnv.getMessager();
}
/**
*
* 对java程序命名进行检查,java名称命名应符合如下格式:
*
*
类或接口:符合驼式命名法,首字母大写*
方法:符合驼式命名法,首字母小写*
字段:符合驼式命名法,首字母小写*
类、实例变量:符合驼式命名法,首字母小写*
常量:要求全部大写*
*
*/
public void checkNames(Element element) {
nameCheckScanner.scan(element);
}
/**
* 名称检查器实现类,继承了jdk1.6中新提供的ElementScanner6
* 将会以Visitor模式访问抽象语法树中的元素
*
*/
private class NameCheckScanner extends ElementScanner6 {
/**
* 此方法用于检查java类
*/
@Override
public Void visitType(TypeElement e, Void p) {
scan(e.getTypeParameters(), p);
checkCamelCase(e, true);
super.visitType(e, p);
return null;
}
/**
* 检查方法命名是否合法
*/
@Override
public Void visitExecutable(ExecutableElement e, Void p) {
if (e.getKind() == ElementKind.METHOD) {
Name name = e.getSimpleName();
if (name.contentEquals(e.getEnclosingElement().getSimpleName()))
messager.printMessage(Kind.WARNING, " 一个普通方法 '" + name + "' 不应该与类名相同,避免与构造方法产生混淆", e);
checkCamelCase(e, false);
}
super.visitExecutable(e, p);
return null;
}
/**
* 检查变量命名是否合法
*/
@Override
public Void visitVariable(VariableElement e, Void p) {
if (e.getKind() == ElementKind.ENUM_CONSTANT || e.getConstantValue() != null || heuristicallyConstant(e))
checkAllCaps(e);
else
checkCamelCase(e, false);
return null;
}
/**
* 判断一个变量是否是常量
*
* @param e
* @return
*/
private boolean heuristicallyConstant(VariableElement e) {
if (e.getEnclosingElement().getKind() == ElementKind.INTERFACE)
return true;
else if (e.getKind() == ElementKind.FIELD
&& e.getModifiers().containsAll(EnumSet.of(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)))
return true;
else {
return false;
}
}
/**
* 检查传入的Element是否符合驼式命名法,如果不符合则输出警告信息
*
* @param e
* @param initialCaps
*/
private void checkCamelCase(Element e, boolean initialCaps) {
String name = e.getSimpleName().toString();
boolean previousUpper = false;
boolean conventional = true;
int firstCodePoint = name.codePointAt(0);
if (Character.isUpperCase(firstCodePoint)) {
previousUpper = true;
if (!initialCaps) {
messager.printMessage(Kind.WARNING, "名称 '" + name + " ' 应当以小写字母开头", e);
return;
}
} else if (Character.isLowerCase(firstCodePoint)) {
if (initialCaps) {
messager.printMessage(Kind.WARNING, "名称 '" + name + " ' 应当以大写字母开头", e);
return;
}
} else
conventional = false;
if (conventional) {
int cp = firstCodePoint;
for (int i = Character.charCount(cp); i < name.length(); i += Character.charCount(cp)) {
cp = name.codePointAt(i);
if (Character.isUpperCase(cp)) {
if (previousUpper) {
conventional = false;
break;
}
previousUpper = true;
} else
previousUpper = false;
}
}
if (!conventional)
messager.printMessage(Kind.WARNING, "名称 '" + name + " ' 应当符合驼式命名法", e);
}
/**
* 大写命名检查,要求第一个字母是大写的英文字母,其余部分是大写字母或下划线
*
* @param e
*/
private void checkAllCaps(VariableElement e) {
String name = e.getSimpleName().toString();
boolean conventional = true;
int firstCodePoint = name.codePointAt(0);
if (!Character.isUpperCase(firstCodePoint)) {
conventional = false;
} else {
boolean previousUnderscore = false;
int cp = firstCodePoint;
for (int i = Character.charCount(cp); i < name.length(); i += Character.charCount(cp)) {
cp = name.codePointAt(i);
if (cp == '_') {
if (previousUnderscore) {
conventional = false;
break;
}
previousUnderscore = true;
} else {
previousUnderscore = false;
if (!Character.isUpperCase(cp) && !Character.isDigit(cp)) {
conventional = false;
break;
}
}
}
}
if (!conventional)
messager.printMessage(Kind.WARNING, "常量 '" + name + " ' 应当全部以大写字母或下划线命名,并且以字母开头", e);
}
}
}