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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java Annotation的RetentionPolicy介绍

發布時間:2025/3/21 java 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java Annotation的RetentionPolicy介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java Annotation對應的Retention有3種,在RetentionPolicy中定義,有3種:

  • SOURCE. 注解保留在源代碼中,但是編譯的時候會被編譯器所丟棄。比如@Override, @SuppressWarnings
  • CLASS. 這是默認的policy。注解會被保留在class文件中,但是在運行時期間就不會識別這個注解。
  • RUNTIME. 注解會被保留在class文件中,同時運行時期間也會被識別。所以可以使用反射機制獲取注解信息。比如@Deprecated
  • RUNTIME

    大部分情況下,我們都是使用RUNTIME這個Policy。

    下面就是一個RUNTIME Annotation的例子。

    先定義Annotation:

    1 2 3 4 5 6 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface MyClassRuntimeAnno { ????String name(); ????int level() default 1; }

    然后在CLASS前面使用這個Annotation。

    1 2 3 @MyClassRuntimeAnno(name = "simple", level = 10) public class SimpleObj { }

    最后寫一個testcase通過反射可以獲取這個類的Annotation進行后續操作。

    1 2 3 4 5 6 7 8 @Test public void testGetAnnotation() { ????Annotation[] annotations = SimpleObj.class.getAnnotations(); ????System.out.println(Arrays.toString(annotations)); ????MyClassRuntimeAnno myClassAnno = SimpleObj.class.getAnnotation(MyClassRuntimeAnno.class); ????System.out.println(myClassAnno.name() + ", " + myClassAnno.level()); ????System.out.println(myClassAnno == annotations[0]); }

    SOURCE

    SOURCE這個policy表示注解保留在源代碼中,但是編譯的時候會被編譯器所丟棄。 由于在編譯的過程中這個注解還被保留著,所以在編譯過程中可以針對這個policy進行一些操作。比如在自動生成java代碼的場景下使用。最常見的就是lombok的使用了,可以自動生成field的get和set方法以及toString方法,構造器等;消除了冗長的java代碼。

    SOURCE這個policy可以使用jdk中的javax.annotation.processing.*包中的processor處理器進行注解的處理過程。

    以1個編譯過程中會打印類中的方法的例子來說明SOUCRE這個policy的作用:

    首先定義一個Printer注解:

    1 2 3 4 @Retention(RetentionPolicy.SOURCE) @Target(ElementType.METHOD) public @interface Printer { }

    然后一個類的方法使用這個注解:

    1 2 3 4 5 6 7 8 9 10 11 12 public class SimpleObject { ????@Printer ????public void methodA() { ????} ????public void methodB() { ????} }

    創建對應的Processor:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @SupportedAnnotationTypes({"me.format.annotaion.Printer"}) public class PrintProcessor extends AbstractProcessor { ????@Override ????public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { ????????Messager messager = processingEnv.getMessager(); ????????messager.printMessage(Diagnostic.Kind.NOTE, "start to use PrintProcessor .."); ????????Set<? extends Element> rootElements = roundEnv.getRootElements(); ????????messager.printMessage(Diagnostic.Kind.NOTE, "root classes: "); ????????for(Element root : rootElements) { ????????????messager.printMessage(Diagnostic.Kind.NOTE, ">> " + root.toString()); ????????} ????????messager.printMessage(Diagnostic.Kind.NOTE, "annotation: "); ????????for(TypeElement te : annotations) { ????????????messager.printMessage(Diagnostic.Kind.NOTE, ">>> " + te.toString()); ????????????Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(te); ????????????for(Element ele : elements) { ????????????????messager.printMessage(Diagnostic.Kind.NOTE, ">>>> " + ele.toString()); ????????????} ????????} ????????return true; ????} ????@Override ????public SourceVersion getSupportedSourceVersion() { ????????return SourceVersion.latestSupported(); ????} }

    然后先使用javac編譯Printer和PrintProcessor:

    1 javac -d classes src/main/java/me/format/annotation/Printer.java src/main/java/me/format/annotation/PrintProcessor.java

    最后再使用javac中的processor參數處理:

    1 javac -cp classes -processor me.format.annotation.PrintProcessor -d classes src/main/java/me/format/annotation/SimpleObject.java

    控制臺打印出:

    1 2 3 4 5 6 注: start to use PrintProcessor .. 注: root classes: 注: >> hello.annotation.SimpleObject 注: annotation: 注: >>> hello.annotation.Printer 注: >>>> methodA()

    CLASS

    CLASS和RUNTIME的唯一區別是RUNTIME在運行時期間注解是存在的,而CLASS則不存在。

    我們通過asm來獲取class文件里的annotation。

    首先定義注解:

    policy為CLASS的注解。

    1 2 3 4 5 6 7 @Retention(RetentionPolicy.CLASS) @Target(ElementType.TYPE) public @interface Meta { ????String name(); }

    policy為RUNTIME的注解。

    1 2 3 4 5 6 7 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Header { ????int code(); }

    使用注解:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Meta(name = "obj") @Header(code = 200) public class AnnotationObject { ????private String val; ????public String getVal() { ????????return val; ????} ????public void setVal(String val) { ????????this.val = val; ????} }

    編譯這3個java文件得到字節碼文件AnnotationObject.class:

    1 javac -d classes src/main/java/me/format/annotaion/AnnotationObject.java src/main/java/me/format/annotation/Meta.java src/main/java/me/format/annotation/Header.java

    使用asm獲取字節碼文件中的注解:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ClassNode classNode = new ClassNode(); ClassReader cr = new ClassReader(new FileInputStream("classes/me/format/annotation/AnnotationObject.class")); cr.accept(classNode, 0); System.out.println("Class Name: " + classNode.name); System.out.println("Source File: " + classNode.sourceFile); System.out.println("invisible: "); AnnotationNode anNode = null; for (Object annotation : classNode.invisibleAnnotations) { ????anNode = (AnnotationNode) annotation; ????System.out.println("Annotation Descriptor : " + anNode.desc); ????System.out.println("Annotation attribute pairs : " + anNode.values); } System.out.println("visible: "); for (Object annotation : classNode.visibleAnnotations) { ????anNode = (AnnotationNode) annotation; ????System.out.println("Annotation Descriptor : " + anNode.desc); ????System.out.println("Annotation attribute pairs : " + anNode.values); }

    打印出:

    1 2 3 4 5 6 7 8 Class Name: me/format/annotation/AnnotationObject Source File: AnnotationObject.java invisible: Annotation Descriptor : Lme/format/annotation/Meta; Annotation attribute pairs : [name, obj] visible: Annotation Descriptor : Lme/format/annotation/Header; Annotation attribute pairs : [code, 200]

    其中policy為CLASS的注解編譯完后不可見,而policy為RUNTIME的注解編譯后可見。

    同樣,我們可以使用javap查看編譯后的信息:

    1 javap -v me.format.annotation.AnnotationObject

    會打印出注解的visible信息:

    1 2 3 4 5 6 7 8 9 #16 = Utf8?????????????? AnnotationObject.java #17 = Utf8?????????????? RuntimeVisibleAnnotations #18 = Utf8?????????????? Lhello/annotation/Header; #19 = Utf8?????????????? code #20 = Integer??????????? 200 #21 = Utf8?????????????? RuntimeInvisibleAnnotations #22 = Utf8?????????????? Lhello/annotation/Meta; #23 = Utf8?????????????? name #24 = Utf8?????????????? obj

    from:?http://www.importnew.com/24051.html

    總結

    以上是生活随笔為你收集整理的Java Annotation的RetentionPolicy介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

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