Java注釋@interface的用法


java用  @interface Annotation{ } 定義一個注解 @Annotation,一個注解是一個類

@Override,@Deprecated,@SuppressWarnings為常見的3個注解。 注解相當於一種標記,在程序中加上了注解就等於為程序加上了某種標記,以后, JAVAC編譯器,開發工具和其他程序可以用反射來了解你的類以及各種元素上有無任何標記,看你有什么標記,就去干相應的事

 

注解@Override用在方法上,當我們想重寫一個方法時,在方法上加@Override,當我們方法的名字出錯時,編譯器就會報錯,如圖:

       注解@Deprecated,用來表示某個類的屬性或方法已經過時,不想別人再用時,在屬性和方法 上用@Deprecated修飾,如圖:

  注解@SuppressWarnings用來壓制程序中出來的警告,比如在沒有用泛型或是方法已經過時的時候,  如圖:

  

注解@Retention可以用來修飾注解,是注解的注解,稱為元注解

Retention注解有一個屬性value,是RetentionPolicy類型的,Enum RetentionPolicy是一個枚舉類型, 這個枚舉決定了Retention注解應該如何去保持,也可理解為Rentention 搭配 RententionPolicy使用。RetentionPolicy有3個值:CLASS  RUNTIME   SOURCE 用@Retention(RetentionPolicy.CLASS)修飾的注解,表示注解的信息被保留在class文件(字節碼文件)中當程序編譯時,但不會被虛擬機讀取在運行的時候; 用@Retention(RetentionPolicy.SOURCE )修飾的注解,表示注解的信息會被編譯器拋棄,不會留在class文件中,注解的信息只會留在源文件中; 用@Retention(RetentionPolicy.RUNTIME )修飾的注解,表示注解的信息被保留在class文件(字節碼文件)中當程序編譯時,會被虛擬機保留在運行時, 所以他們可以用反射的方式讀取。RetentionPolicy.RUNTIME 可以讓你從JVM中讀取Annotation注解的信息,以便在分析程序的時候使用.

復制代碼
package com.self; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface MyTarget { } 
復制代碼

定義個一注解@MyTarget,用RetentionPolicy.RUNTIME修飾;

復制代碼
package com.self; import java.lang.reflect.Method; public class MyTargetTest { @MyTarget public void doSomething() { System.out.println("hello world"); } public static void main(String[] args) throws Exception { Method method = MyTargetTest.class.getMethod("doSomething",null); if(method.isAnnotationPresent(MyTarget.class))//如果doSomething方法上存在注解@MyTarget,則為true  { System.out.println(method.getAnnotation(MyTarget.class)); } } } 
復制代碼

上面程序打印:@com.self.MyTarget(),如果RetentionPolicy值不為RUNTIME,則不打印

復制代碼
@Retention(RetentionPolicy.SOURCE )  
public @interface Override @Retention(RetentionPolicy.SOURCE ) public @interface SuppressWarnings @Retention(RetentionPolicy.RUNTIME ) public @interface Deprecated 
復制代碼

由上可以看出,只有注解@Deprecated在運行時可以被JVM讀取到  

注解中可以定義屬性,看例子:

復制代碼
@Retention(RetentionPolicy.RUNTIME)  
public @interface MyAnnotation { String hello() default "gege"; String world(); int[] array() default { 2, 4, 5, 6 }; EnumTest.TrafficLamp lamp() ; TestAnnotation lannotation() default @TestAnnotation(value = "ddd"); Class style() default String.class; } 
復制代碼

上面程序中,定義一個注解@MyAnnotation,定義了6個屬性,他們的名字為:  

hello,world,array,lamp,lannotation,style.  

  • 屬性hello類型為String,默認值為gege  
  • 屬性world類型為String,沒有默認值  
  • 屬性array類型為數組,默認值為2,4,5,6  
  • 屬性lamp類型為一個枚舉,沒有默認值  
  • 屬性lannotation類型為注解,默認值為@TestAnnotation,注解里的屬性是注解  
  • 屬性style類型為Class,默認值為String類型的Class類型  

看下面例子:定義了一個MyTest類,用注解@MyAnnotation修飾,注解@MyAnnotation定義的屬性都賦了值

復制代碼
@MyAnnotation(hello = "beijing", world="shanghai",array={},lamp=TrafficLamp.RED,style=int.class) public class MyTest { @MyAnnotation(lannotation=@TestAnnotation(value="baby"), world = "shanghai",array={1,2,3},lamp=TrafficLamp.YELLOW) @Deprecated @SuppressWarnings("") public void output() { System.out.println("output something!"); } } 
復制代碼

接着通過反射讀取注解的信息:  

復制代碼
public class MyReflection { public static void main(String[] args) throws Exception { MyTest myTest = new MyTest(); Class<MyTest> c = MyTest.class; Method method = c.getMethod("output", new Class[] {}); //如果MyTest類名上有注解@MyAnnotation修飾,則為true if(MyTest.class.isAnnotationPresent(MyAnnotation.class)) { System.out.println("have annotation"); } if (method.isAnnotationPresent(MyAnnotation.class)) { method.invoke(myTest, null); //調用output方法 //獲取方法上注解@MyAnnotation的信息 MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class); String hello = myAnnotation.hello(); String world = myAnnotation.world(); System.out.println(hello + ", " + world);//打印屬性hello和world的值 System.out.println(myAnnotation.array().length);//打印屬性array數組的長度 System.out.println(myAnnotation.lannotation().value()); //打印屬性lannotation的值  System.out.println(myAnnotation.style()); } //得到output方法上的所有注解,當然是被RetentionPolicy.RUNTIME修飾的 Annotation[] annotations = method.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation.annotationType().getName()); } } } 
復制代碼

上面程序打印:  

復制代碼
have annotation  
output something! gege, shanghai 3 baby class java.lang.String com.heima.annotation.MyAnnotation java.lang.Deprecated 
復制代碼

如果注解中有一個屬性名字叫value,則在應用時可以省略屬性名字不寫。  

可見,@Retention(RetentionPolicy.RUNTIME )注解中,RetentionPolicy.RUNTIME是注解屬性值,屬性名字是value,  

屬性的返回類型是RetentionPolicy,如下:

public @interface MyTarget { String value(); } 

可以這樣用:  

@MyTarget("aaa")  
 public void doSomething() { System.out.println("hello world"); } 

注解@Target也是用來修飾注解的元注解,它有一個屬性ElementType也是枚舉類型,  

值為:ANNOTATION_TYPE CONSTRUCTOR  FIELD LOCAL_VARIABLE METHOD PACKAGE PARAMETER TYPE  

@Target(ElementType.METHOD) 修飾的注解表示該注解只能用來修飾在方法上

復制代碼
@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.RUNTIME)  
public @interface MyTarget { String value() default "hahaha"; } 
復制代碼

如把@MyTarget修飾在類上,則程序報錯,如:

@MyTarget  
public class MyTargetTest 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM