Java注释@interface

来源:互联网 发布:mac 系统没装上 按d 编辑:程序博客网 时间:2024/05/19 17:09

       java用  @interfaceAnnotation{ } 定义一个注解@Annotation,一个注解是一个类。

@Override,@Deprecated,@SuppressWarnings为常见的3个注解。
注解相当于一种标记,在程序中加上了注解就等于为程序加上了某种标记,以后,
JAVAC编译器,开发工具和其他程序可以用反射来了解你的类以及各种元素上有无任何标记,看你有什么标记,就去干相应的事。

      注解@Override用在方法上,当我们想重写一个方法时,在方法上加@Override,当我们方法
的名字出错时,编译器就会报错,如图:


       注解@Deprecated,用来表示某个类的属性或方法已经过时,不想别人再用时,在属性和方法
上用@Deprecated修饰,如图:

 

  注解@SuppressWarnings用来压制程序中出来的警告,比如在没有用泛型或是方法已经过时的时候,
 如图:

  

@Retention

可以用来修饰注解,是注解的注解,称为元注解。
Retention
注解有一个属性value,是RetentionPolicy类型的,EnumRetentionPolicy是一个枚举类型,这个枚举决定了Retention注解应该如何去保持,也可理解为Rentention搭配RententionPolicy使用。RetentionPolicy3个值:CLASS RUNTIME   SOURCE


@Retention(RetentionPolicy.CLASS)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,但不会被虚拟机读取在运行的时候;
@Retention(RetentionPolicy.SOURCE)修饰的注解,表示注解的信息会被编译器抛弃,不会留在class文件中,注解的信息只会留在源文件中;
@Retention(RetentionPolicy.RUNTIME)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,会被虚拟机保留在运行时,

 

@Target:

指定程序元定义的注释所使用的地方,它使用了另一个类:ElementType,是一个枚举类定义了注释类型可以应用到不同的程序元素以免使用者误用。看看java.lang.annotation 下的源代码: 

@Documented  
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.ANNOTATION_TYPE)  
public @interface Target {  
    ElementType[] value();  



     ElementType是一个枚举类型,指明注释可以使用的地方,看看ElementType类: 
public enum ElementType {  

     TYPE, // 指定适用点为 class, interface, enum  
     FIELD, // 指定适用点为 field  
     METHOD, // 指定适用点为 method  
     PARAMETER, // 指定适用点为 method 的 parameter  
     CONSTRUCTOR, // 指定适用点为 constructor  
     LOCAL_VARIABLE, // 指定使用点为 局部变量  
     ANNOTATION_TYPE, //指定适用点为 annotation 类型  
     PACKAGE // 指定适用点为 package  

 

 @Documented:是一个标记注释,表示注释应该出现在类的javadoc中,因为在默认情况下注释时不包括在javadoc中的。 

所以如果花费了大量的时间定义一个注释类型,并想描述注释类型的作用,可以使用它。 

注意他与@Retention(RetentionPolicy.RUNTIME)配合使用,因为只有将注释保留在编译后的类文件中由虚拟机加载, 

然后javadoc才能将其抽取出来添加至javadoc中。 


     @Inherited将注释同样继承至使用了该注释类型的方法中(表达有点问题,就是如果一个方法使用了的注释用了@inherited, 

那么其子类的该方法同样继承了该注释) 
注意事项: 
     1.所有的Annotation自动继承java.lang.annotation接口 
     2.自定义注释的成员变量访问类型只能是public、default;(所有的都能访问,源作者没用到函数:getDeclaredFields而已) 
     3.成员变量的只能使用基本类型(byte、short、int、char、long、double、float、boolean和String、Enum、Class、annotations以及该类型的数据)(没有限制,大家可以修改测试一下,就清楚) 
     4.如果只有一个成员变量,最好将参数名称设为value,赋值时不用制定名称而直接赋值 
     5.在实际应用中,还可以使用注释读取和设置Bean中的变量。 


可以用反射的方式读取。RetentionPolicy.RUNTIME 可以让你从JVM中读取Annotation注解的信息,以便在分析程序的时候使用.

[java] view plain copy

1.     package com.self;  

2.     import java.lang.annotation.Retention;  

3.     import java.lang.annotation.RetentionPolicy;  

4.       

5.     @Retention(RetentionPolicy.RUNTIME)  

6.     public @interface MyTarget  

7.     { }  

8.     定义个一注解@MyTarget,用RetentionPolicy.RUNTIME修饰;  

9.     package com.self;  

10.   import java.lang.reflect.Method;  

11.   public class MyTargetTest  

12.   {  

13.     @MyTarget  

14.    public void doSomething()  

15.     {  

16.     System.out.println("hello world");  

17.     }  

18.      

19.     public static void main(String[] args) throws Exception  

20.    {  

21.      Method method = MyTargetTest.class.getMethod("doSomething",null);  

22.     if(method.isAnnotationPresent(MyTarget.class))//如果doSomething方法上存在注解@MyTarget,则为true  

23.      {  

24.      System.out.println(method.getAnnotation(MyTarget.class));  

25.      }  

26.     }  

27.    }  

28.   上面程序打印:@com.self.MyTarget(),如果RetentionPolicy值不为RUNTIME,则不打印。  

29.      

30.    @Retention(RetentionPolicy.SOURCE )  

31.   public @interface Override  

32.     

33.   @Retention(RetentionPolicy.SOURCE )  

34.   public @interface SuppressWarnings  

35.      

36.   @Retention(RetentionPolicy.RUNTIME )  

37.   public @interface Deprecated  

38.   由上可以看出,只有注解@Deprecated在运行时可以被JVM读取到  

39.      

注解中可以定义属性,看例子:  

40.   @Retention(RetentionPolicy.RUNTIME)  

41.   public @interface MyAnnotation  

42.    {  

43.    String hello() default "gege";  

44.      String world();  

45.     int[] array() default { 2456 };  

46.      EnumTest.TrafficLamp lamp() ;  

47.     TestAnnotation lannotation() default @TestAnnotation(value = "ddd");  

48.      Class style() default String.class;  

49.   }  

50.    上面程序中,定义一个注解@MyAnnotation,定义了6个属性,他们的名字为:  

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

52.    属性hello类型为String,默认值为gege  

53.   属性world类型为String,没有默认值  

54.    属性array类型为数组,默认值为2456  

55.   属性lamp类型为一个枚举,没有默认值  

56.    属性lannotation类型为注解,默认值为@TestAnnotation,注解里的属性是注解  

57.   属性style类型为Class,默认值为String类型的Class类型  

58.      

59.   看下面例子:定义了一个MyTest类,用注解@MyAnnotation修饰,注解@MyAnnotation定义的属性都赋了值  

----------------------------------

60.   @MyAnnotation(hello = "beijing", world="shanghai",array={},lamp=TrafficLamp.RED,style=int.class)  

61.   public class MyTest  

62.    {  

63.    @MyAnnotation(lannotation=@TestAnnotation(value="baby"), world = "shanghai",array={1,2,3},lamp=TrafficLamp.YELLOW)  

64.     @Deprecated  

65.    @SuppressWarnings("")  

66.     public void output()  

67.    {  

68.      System.out.println("output something!");  

69.    }  

70.    }  

71.----------------------------------

72.    

73.    接着通过反射读取注解的信息:  

74.   public class MyReflection  

75.   {  

76.     public static void main(String[] args) throws Exception  

77.    {  

78.      MyTest myTest = new MyTest();  

79.       Class<MyTest> c = MyTest.class;  

80.        Method method = c.getMethod("output"new Class[] {});  

81.          //如果MyTest类名上有注解@MyAnnotation修饰,则为true  

82.      if(MyTest.class.isAnnotationPresent(MyAnnotation.class))  

83.     {  

84.       System.out.println("have annotation");  

85.     }  

86.       if (method.isAnnotationPresent(MyAnnotation.class))  

87.      {  

88.       method.invoke(myTest, null); //调用output方法  

89.      //获取方法上注解@MyAnnotation的信息  

90.         MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);  

91.       String hello = myAnnotation.hello();  

92.       String world = myAnnotation.world();  

93.      System.out.println(hello + ", " + world);//打印属性helloworld的值  

94.       System.out.println(myAnnotation.array().length);//打印属性array数组的长度  

95.      System.out.println(myAnnotation.lannotation().value()); //打印属性lannotation的值  

96.       System.out.println(myAnnotation.style());  

97.      }  

98.        //得到output方法上的所有注解,当然是被RetentionPolicy.RUNTIME修饰的  

99.        Annotation[] annotations = method.getAnnotations();  

100.         for (Annotation annotation : annotations)  

101.    {  

102.      System.out.println(annotation.annotationType().getName());  

103.    }  

104.      }  

105.  }  

106.   上面程序打印:  

107.  have annotation  

108.   output something!  

109.  gege, shanghai  

110.  3  

111.  baby  

112.  class java.lang.String  

113.  com.heima.annotation.MyAnnotation  

114.   java.lang.Deprecated  

115.    

116.  如果注解中有一个属性名字叫value,则在应用时可以省略属性名字不写。  

117.  可见,@Retention(RetentionPolicy.RUNTIME )注解中,RetentionPolicy.RUNTIME是注解属性值,属性名字是value,  

118.   属性的返回类型是RetentionPolicy,如下:  

119.  public @interface MyTarget  

120.   {  

121.      String value();  

122.   }  

123.  可以这样用:  

124.     @MyTarget("aaa")  

125.   public void doSomething()  

126.    {  

127.    System.out.println("hello world");  

128.    }  

129.     

130.  注解@Target也是用来修饰注解的元注解,它有一个属性ElementType也是枚举类型,  

131.  值为ANNOTATION_TYPE CONSTRUCTOR  FIELD LOCAL_VARIABLE METHOD PACKAGE PARAMETER TYPE  

132.  @Target(ElementType.METHOD) 修饰的注解表示该注解只能用来修饰在方法上。  

133.  @Target(ElementType.METHOD)  

134.  @Retention(RetentionPolicy.RUNTIME)  

135.  public @interface MyTarget  

136.   {  

137.   String value() default "hahaha";  

138.   }  

139.  如把@MyTarget修饰在类上,则程序报错,如:  

140.  @MyTarget  

141.  public class MyTargetTest  

142.   注解大都用在开发框架中吧,好了有关注解就学习那么多了,谢谢。  

 

0 0
原创粉丝点击