日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java编译器代码检查_java 命名代码检查-注解处理器

發布時間:2024/9/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java编译器代码检查_java 命名代码检查-注解处理器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

命名代碼檢查

根據 中第6.8節的要求, Java 程序命名應當符合下列格式的書寫規范:

類 ( 或接口 ) : 符合駝式命名法, 首字母大寫.

方法 : 符合駝式命名法,首字母小寫

字段 :類或實例變量 : 符合駝式命名法 , 首字母小寫

常量 : 要求全部有大寫字母或下劃線構成, 并且第一個字符不能是下劃線.

要通過注解處理器的API 實現一個編譯器插件 , 首先需要了解這組 API 的基本知識.我們實現注解處理器的代碼需要繼承抽象類 javax.annotation.processing.AbstractProcessor ,這個抽象類中只有一個必須覆蓋的abstract方法 : "process()" ?它是 javac 編譯器在執行注解處理器代碼時需要調用的過程 , 我們可以從這個方法的第一個參數 'annotations' 中獲取到此注解處理器所要求處理的注解集合,從第二個參數 'roundEnv' 中訪問到當前這個 round 中得語法樹節點, 每個語法樹節點在這里表示為一個 Element ?, 在 JDK1.6 新增的 javax.lang.model 包中定義了16類 Element , 包括了 Java 代碼中最常用的元素,

如 : '包( PACKAGE ) , 枚舉 ( ENUM ) ?, 類 ( CLASS ) , 注解 (ANNOTATION_TYPE) , 接口 (INTERFACE ) , 枚舉值 ( ENUM_VARIABLE ) ,字段 ( FIELD ) , 參數 ( PARAMETER ) , 本地變量 ( LOCAL_VARIABLE ) , 異常 ( EXCEPTOIN_PARAMETER ) ?,方法 ( METHOD ) , 構造函數 (CONSTRUCTOR ) 靜態塊語句 ( STATIC_INIT ,即 static {} 塊 ) ,實例語句塊 (INSTANCE_INIT, 即{}塊) , 參數化類型 ( TYPE_PARAMETER ) , 和未定義的其他語法樹節點 ( OTHER ) ;

除了 process () 方法的傳入參數之外, 還有一個很常用的實例變量' processingEnv' ,它是 AbstractProcessor 中的一個 protected 變量, 在注解處理器代碼可以直接訪問到它,它代表了注解處理器框架提供了一個上下文環境,眼創建新的代碼,向編譯器輸出信息,獲取其他工具類等都需要用到這個實例變量,

注解處理器除了 process 方法及其參數外,還有兩個可以配合使用的 Annotations :@SupportedAnnotationTypes 和@SupportedSourceVersion 前者代表這個注解處理器對哪些注解感興趣,可以使用 '*' 作為通配符表示對所有的感興趣.后者指出這個注解處理器可以處理哪些版本的 Java 代碼.

每個注解處理器在運行的時候都是單例的.如果不需要改變生成語法樹的內容, process() 方法就可以返回一個值為 false 的布爾值,通知編譯器這個 round 中得代碼未發生變化, 無需構造新的 JavaCompiler 實例,在這里只對程序命名進行檢查 , 不需要改變語法樹的內容, 因此process() 方法的返回值都是 false

實例如下:

AbstractProcessor

packageannotation.processing;importjava.util.EnumSet;importjava.util.Set;importjavax.annotation.processing.AbstractProcessor;importjavax.annotation.processing.Messager;importjavax.annotation.processing.ProcessingEnvironment;importjavax.annotation.processing.RoundEnvironment;importjavax.annotation.processing.SupportedAnnotationTypes;importjavax.annotation.processing.SupportedSourceVersion;importjavax.lang.model.SourceVersion;importjavax.lang.model.element.Element;importjavax.lang.model.element.ElementKind;importjavax.lang.model.element.ExecutableElement;importjavax.lang.model.element.Name;importjavax.lang.model.element.TypeElement;importjavax.lang.model.element.VariableElement;importjavax.lang.model.util.ElementScanner6;importjavax.tools.Diagnostic.Kind;//使用*表示支持所有的Annotations/*** 以下代碼出自 《深入理解Java虛擬機:JVM高級特性與最佳實踐》

**/@SupportedAnnotationTypes("*")//表示只對 JDK 1.6 的 Java 源碼感興趣

@SupportedSourceVersion(value =SourceVersion.RELEASE_6)public class NameCheckProcessor extendsAbstractProcessor {

@Overridepublic synchronized voidinit(ProcessingEnvironment processingEnv) {super.init(processingEnv);this.nameCheck = newNameCheck(processingEnv);

}privateNameCheck nameCheck;

@Overridepublic boolean process(Set extends TypeElement>annotations,

RoundEnvironment roundEnv) {if (!roundEnv.processingOver()) {for(Element element : roundEnv.getRootElements()) {

nameCheck.check(element);

}

}return false;

}/*** 程序名稱規范的編譯器插件 如果程序命名不合規范,將會輸出一個編譯器的Warning信息

*

*@authorkevin

**/

static classNameCheck {

Messager messager= null;publicNameCheckScanner nameCheckScanner;privateNameCheck(ProcessingEnvironment processingEnv) {

messager=processingEnv.getMessager();

nameCheckScanner= newNameCheckScanner(processingEnv);

}/*** 對Java程序明明進行檢查,根據《Java語言規范(第3版)》6.8節的要求,Java程序命名應當符合下列格式:

*

*

類或接口:符合駝式命名法,首字母大寫。

*

方法:符合駝式命名法,首字母小寫。

*

字段:

*

*

類,實例變量:符合駝式命名法,首字母小寫。

*

常量:要求全部大寫

*

*

*

*@paramelement*/

public voidcheck(Element element) {

nameCheckScanner.scan(element);

}/*** 名稱檢查器實現類,繼承了1.6中新提供的ElementScanner6

* 將會以Visitor模式訪問抽象語法數中得元素

*

**/

static class NameCheckScanner extends ElementScanner6{

Messager messager= null;publicNameCheckScanner(ProcessingEnvironment processingEnv) {this.messager =processingEnv.getMessager();

}/*** 此方法用于檢查Java類*/@OverridepublicVoid visitType(TypeElement e, Void p) {

scan(e.getTypeParameters(), p);

checkCamelCase(e,true);super.visitType(e, p);return null;

}/*** 檢查傳入的Element是否符合駝式命名法,如果不符合,則輸出警告信息

*

*@parame

*@paramb*/

private void checkCamelCase(Element e, booleaninitialCaps) {

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+ "應當符合駝式命名法(Camel Case Names)", e);

}

}/*** 檢查方法命名是否合法*/@OverridepublicVoid 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;

}/*** 檢查變量是否合法*/@OverridepublicVoid visitVariable(VariableElement e, Void p) {/*如果這個Variable是枚舉或常量,則按大寫命名檢查,否則按照駝式命名法規則檢查*/

if (e.getKind() ==ElementKind.ENUM_CONSTANT|| e.getConstantValue() != null

||heuristicallyConstant(e)) {

checkAllCaps(e);

}else{

checkCamelCase(e,false);

}super.visitVariable(e, p);return null;

}/*** 大寫命名檢查,要求第一個字符必須是大寫的英文字母,其余部分可以下劃線或大寫字母

*

*@parame*/

private voidcheckAllCaps(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 == (int) '_') {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);

}

}/*** 判斷一個變量是否是常量

*

*@parame

*@return

*/

private booleanheuristicallyConstant(VariableElement e) {if (e.getEnclosingElement().getKind() ==ElementKind.INTERFACE) {return true;

}else if (e.getKind() ==ElementKind.FIELD&&e.getModifiers()

.containsAll(

EnumSet.of(

javax.lang.model.element.Modifier.FINAL,

javax.lang.model.element.Modifier.STATIC,

javax.lang.model.element.Modifier.PUBLIC))) {return true;

}return false;

}

}

}

}

測試代碼:

BADLY_NAMED_CODE

packageannotation.processing;public classBADLY_NAMED_CODE {enumColors {

Red, Blue, Green;

}static final int FORTY_TWO =42;public static int NOT_A_CONSTANT =FORTY_TWO;protected voidBadly_Named_Code() {return;

}public voidNOTcamelCASEmethodNAME() {return;

}

}

執行過程如下:

bogon:Desktop mjorcen$ javac annotation/processing/BADLY_NAMED_CODE.java

bogon:Desktop mjorcen$ javac annotation/processing/NameCheckProcessor.java

bogon:Desktop mjorcen$ javac-processor annotation.processing.NameCheckProcessor annotation/processing/BADLY_NAMED_CODE.java

警告: 來自注釋處理程序'annotation.processing.NameCheckProcessor' 的受支持 source 版本 'RELEASE_6' 低于 -source '1.7'annotation/processing/BADLY_NAMED_CODE.java:2: 警告: 名稱:BADLY_NAMED_CODE應當符合駝式命名法(Camel Case Names)public classBADLY_NAMED_CODE {^annotation/processing/BADLY_NAMED_CODE.java:5: 警告: 常量:Red 應該全部以大寫字母或下劃線命名,并且以字符開頭

Red, Blue, Green;^annotation/processing/BADLY_NAMED_CODE.java:5: 警告: 常量:Blue 應該全部以大寫字母或下劃線命名,并且以字符開頭

Red, Blue, Green;^annotation/processing/BADLY_NAMED_CODE.java:5: 警告: 常量:Green 應該全部以大寫字母或下劃線命名,并且以字符開頭

Red, Blue, Green;^annotation/processing/BADLY_NAMED_CODE.java:9: 警告: 名稱:NOT_A_CONSTANT 應當以小寫字母開頭public static int NOT_A_CONSTANT =FORTY_TWO;^

6 個警告

....

以上內容出自:

《深入理解Java虛擬機:JVM高級特性與最佳實踐》

將這個處理器注冊到 Eclipse 上,我建立如下 META-INF 文件:

META-INF/services/javax.annotation.processing.Processor:

annotation.processing.NameCheckProcessor

這里只包含了處理器實現類的類名。我不確定你是否可以在這里列出多個處理器。

就這樣。現在導出一個 jar 文件,并且在你需要用到這個處理器的工程上導入這個文件。

第二步:建立一個使用你的處理器的工程

In the properties for your new project go to?Java Compiler -> Annotation Processing

Check the?“Enable Project Specific Settings”?and make sure?“Enable annotation processing”?is checked. I also changed the generated source directory to a name which didn’t start with a dot so it wouldn’t be hidden in the package explorer (files or directories which start with a dot are by default filtered away in eclipse).

在工程的屬性中找到??Java Compiler -> Annotation Processing查看?“Enable Project Specific Settings”?確認?“Enable annotation processing”?被選中。為了不讓他在包瀏覽器中隱藏,我還修改了??generated source directory?,去掉了開始的點(Eclipse 會將文件名以點開始的文件或文件夾過濾掉)。

然后,轉到??Java Compiler -> Annotation Processing -> Factory Path你可以在這里導入處理器的 jar 文件。不可以使用工程引用。

點擊?“Advanced”?按鈕,會顯示一個對話框,列出了??META-INF/services/javax.annotation.processing.Processor?文件中的內容。選擇它并按OK。

第三步:Build!

完成了。這是在我的工程里顯示的樣子:

總結

以上是生活随笔為你收集整理的java编译器代码检查_java 命名代码检查-注解处理器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。