注解的使用

来源:互联网 发布:win10 蓝牙共享网络 编辑:程序博客网 时间:2024/06/12 01:41

我们知道注解是在JDK1.5引入的,可能有的人没有用过注解,所以感觉注解这个东西没有什么用,但是深入了解注解,对以后学习框架有所帮助的,后面提到的JavaWeb的框架中很多都是基于注解的技术,

其实注解你可以把他认为是一种标记,和接口差不多,我们知道有些接口只起到标记作用(通常叫做标记接口如:Serializable,Cloneable等,就是接口中没有任何东西,只做为一种标记),下面来看一下注解的定义和使用的方法:

定义一个注解和接口差不多:使用关键字@interface

代码如下:

[java] view plain copy
  1. package com.annotation.demo;  
  2.   
  3. import java.lang.annotation.ElementType;  
  4. import java.lang.annotation.Retention;  
  5. import java.lang.annotation.RetentionPolicy;  
  6. import java.lang.annotation.Target;  
  7.   
  8. @Retention(RetentionPolicy.RUNTIME)  
  9. //javac将源程序编译成class文件,在这个过程中类上的注解是否保留到class文件中  
  10. //注解的生命周期的三个阶段:源程序,class文件,字节码  
  11. //默认值是在class阶段  
  12. //Override SuppressWarning Deprecated:按照编译器的标准来判断这三个阶段  
  13. @Target({ElementType.ANNOTATION_TYPE,ElementType.TYPE,ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.LOCAL_VARIABLE,ElementType.METHOD,ElementType.PACKAGE,ElementType.PARAMETER})  
  14. //注解添加的目标  
  15. public @interface MyAnnotation{  
  16.       
  17.     String color() default "red";//属性String  
  18.     int[] value() default {1};//属性int[],这是个特殊的属性,如果只有一个value属性需要去设置值,可以不需要设置"value="  
  19.     MyEnum enums() default MyEnum.ONE;//属性enum,返回值是MyEnum枚举  
  20.     MetaAnnotation annotation() default @MetaAnnotation("red");//注解属性  
  21.     //静态常量  
  22.     boolean isRunning = false;  
  23.   
  24. }  
这个注解上面我们又添加了Java中已经定义的注解:@Retention和@Target,下面来讲解一下这两个注解的作用

首先来看一下@Retention注解的作用:他的作用是标记该注解的生命周期(即三个阶段:Java源程序,class文件,字节码),看一下他的源代码:

[java] view plain copy
  1. /* 
  2.  * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. 
  3.  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 
  4.  */  
  5.   
  6. package java.lang.annotation;  
  7.   
  8. /** 
  9.  * Indicates how long annotations with the annotated type are to 
  10.  * be retained.  If no Retention annotation is present on 
  11.  * an annotation type declaration, the retention policy defaults to 
  12.  * {@code RetentionPolicy.CLASS}. 
  13.  * 
  14.  * <p>A Retention meta-annotation has effect only if the 
  15.  * meta-annotated type is used directly for annotation.  It has no 
  16.  * effect if the meta-annotated type is used as a member type in 
  17.  * another annotation type. 
  18.  * 
  19.  * @author  Joshua Bloch 
  20.  * @since 1.5 
  21.  */  
  22. @Documented  
  23. @Retention(RetentionPolicy.RUNTIME)  
  24. @Target(ElementType.ANNOTATION_TYPE)  
  25. public @interface Retention {  
  26.     RetentionPolicy value();  
  27. }  
@Retention注解中只有一个value属性,这个属性的类型是一个枚举类型,有三个值SOURCE,CLASS,RUNTIME
[java] view plain copy
  1. /* 
  2.  * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. 
  3.  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 
  4.  */  
  5.   
  6. package java.lang.annotation;  
  7.   
  8. /** 
  9.  * Annotation retention policy.  The constants of this enumerated type 
  10.  * describe the various policies for retaining annotations.  They are used 
  11.  * in conjunction with the {@link Retention} meta-annotation type to specify 
  12.  * how long annotations are to be retained. 
  13.  * 
  14.  * @author  Joshua Bloch 
  15.  * @since 1.5 
  16.  */  
  17. public enum RetentionPolicy {  
  18.     /** 
  19.      * Annotations are to be discarded by the compiler. 
  20.      */  
  21.     SOURCE,  
  22.   
  23.     /** 
  24.      * Annotations are to be recorded in the class file by the compiler 
  25.      * but need not be retained by the VM at run time.  This is the default 
  26.      * behavior. 
  27.      */  
  28.     CLASS,  
  29.   
  30.     /** 
  31.      * Annotations are to be recorded in the class file by the compiler and 
  32.      * retained by the VM at run time, so they may be read reflectively. 
  33.      * 
  34.      * @see java.lang.reflect.AnnotatedElement 
  35.      */  
  36.     RUNTIME  
  37. }  
从注释中可以看出,

SOURCE:是将注解保存在源程序中,但是会被编译器遗弃的,就是不会保留到class文件中了,而且这个是默认值

CLASS:是将注解会被编译器保存到class文件中,但是不会保留到VM运行的时候,就是会被在JVM加载字节码的时候遗弃

RUNTIME:是将注解保存到运行的时候,这时候也就可以使用反射技术获取到这个注解的实例对象了

下面来看一下例子:

在定义一个注解,这个注解是被定义在MyAnnotation注解中的,我们叫这样的注解是原注解:

[java] view plain copy
  1. package com.annotation.demo;  
  2.   
  3. public @interface MetaAnnotation {  
  4.       
  5.     String name() default "red";  
  6.     String value();  
  7.   
  8. }  

还有我们自定义了枚举:

[java] view plain copy
  1. package com.annotation.demo;  
  2.   
  3. public enum MyEnum {  
  4.     ONE,TWO,THREE;  
  5. }  

在来看一下,使用了MyAnnotation注解的类:
[java] view plain copy
  1. package com.annotation.demo;  
  2.   
  3. @MyAnnotation(color="red",value={1,2,3},enums=MyEnum.ONE)  
  4. public class UseAnnotation {  
  5.   
  6.     public void fun(){  
  7.     }  
  8.       
  9. }  
这个注解的具体使用,后面再说,我们现在先来看一下上面提到的@Retention注解的作用,最后来看一下获取到UseAnnotation类上的注解:
[java] view plain copy
  1. package com.annotation.demo;  
  2.   
  3. public class AnnotationTest {  
  4.   
  5.     public static void main(String[] args){  
  6.         //UserAnnotation类中使用到了MyAnnotation自定的注解  
  7.         UseAnnotation.class.isAnnotationPresent(MyAnnotation.class);  
  8.         //获取UserAnnotation中上的注解  
  9.         MyAnnotation annotation = (MyAnnotation) UseAnnotation.class.getAnnotation(MyAnnotation.class);  
  10.         //打印注解  
  11.         System.out.println(annotation);  
  12.         System.out.println(annotation.color());  
  13.         System.out.println(annotation.enums());  
  14.         System.out.println(annotation.value().length);  
  15.     }  
  16.       
  17. }  
运行结果:


打印出来了注解

下面我们将MyAnnotation注解中的@Retention(RetentionPolicy.RUNTIME)注解改成@Retention(RetentionPolicy.SOURCE),这时候在运行:


发现运行打印的枚举结果是null,如果将@Retention(RetentionPolicy.CLASS)效果也是一样的,这个就是和我们上面所说的那样,这个注解没有保存到运行的时候,我们是无从类中获取到注解的实例对象的,这样@Retention注解类型的作用就清楚了,刚开始搞这个东西的时候,总是打印出来的是null,而@Retention的默认值是SOURCE,找了很多资料,才搞定的,很纠结呀!

下面在来看一下@Target注解:

源代码如下:

[java] view plain copy
  1. /* 
  2.  * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. 
  3.  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 
  4.  */  
  5.   
  6. package java.lang.annotation;  
  7.   
  8. /** 
  9.  * Indicates the kinds of program element to which an annotation type 
  10.  * is applicable.  If a Target meta-annotation is not present on an 
  11.  * annotation type declaration, the declared type may be used on any 
  12.  * program element.  If such a meta-annotation is present, the compiler 
  13.  * will enforce the specified usage restriction. 
  14.  * 
  15.  * For example, this meta-annotation indicates that the declared type is 
  16.  * itself a meta-annotation type.  It can only be used on annotation type 
  17.  * declarations: 
  18.  * <pre> 
  19.  *    @Target(ElementType.ANNOTATION_TYPE) 
  20.  *    public @interface MetaAnnotationType { 
  21.  *        ... 
  22.  *    } 
  23.  * </pre> 
  24.  * This meta-annotation indicates that the declared type is intended solely 
  25.  * for use as a member type in complex annotation type declarations.  It 
  26.  * cannot be used to annotate anything directly: 
  27.  * <pre> 
  28.  *    @Target({}) 
  29.  *    public @interface MemberType { 
  30.  *        ... 
  31.  *    } 
  32.  * </pre> 
  33.  * It is a compile-time error for a single ElementType constant to 
  34.  * appear more than once in a Target annotation.  For example, the 
  35.  * following meta-annotation is illegal: 
  36.  * <pre> 
  37.  *    @Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD}) 
  38.  *    public @interface Bogus { 
  39.  *        ... 
  40.  *    } 
  41.  * </pre> 
  42.  */  
  43. @Documented  
  44. @Retention(RetentionPolicy.RUNTIME)  
  45. @Target(ElementType.ANNOTATION_TYPE)  
  46. public @interface Target {  
  47.     ElementType[] value();  
  48. }  
他里面也只有一个属性value,是个ElementType类型的数组:

看一下ElementType源代码:

[java] view plain copy
  1. /* 
  2.  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 
  3.  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 
  4.  */  
  5.   
  6. package java.lang.annotation;  
  7.   
  8. /** 
  9.  * A program element type.  The constants of this enumerated type 
  10.  * provide a simple classification of the declared elements in a 
  11.  * Java program. 
  12.  * 
  13.  * <p>These constants are used with the {@link Target} meta-annotation type 
  14.  * to specify where it is legal to use an annotation type. 
  15.  * 
  16.  * @author  Joshua Bloch 
  17.  * @since 1.5 
  18.  */  
  19. public enum ElementType {  
  20.     /** Class, interface (including annotation type), or enum declaration */  
  21.     TYPE,  
  22.   
  23.     /** Field declaration (includes enum constants) */  
  24.     FIELD,  
  25.   
  26.     /** Method declaration */  
  27.     METHOD,  
  28.   
  29.     /** Parameter declaration */  
  30.     PARAMETER,  
  31.   
  32.     /** Constructor declaration */  
  33.     CONSTRUCTOR,  
  34.   
  35.     /** Local variable declaration */  
  36.     LOCAL_VARIABLE,  
  37.   
  38.     /** Annotation type declaration */  
  39.     ANNOTATION_TYPE,  
  40.   
  41.     /** Package declaration */  
  42.     PACKAGE  
  43. }  
这里可以看到总共有TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,ANNOTATION_TYPE,PACKAGE这七个值分别表示的是添加注解的对象类型:

TYPE:是Java1.5引入的新类型,他概括了所有的类型,不止是Class类,还有枚举Enum等,所以这里没有用CLASS类型了

FIELD:是类中的字段

METHOD:是类中的方法

PARAMETER:是方法中的形参(传递的参数类型)

CONSTRUCTOR:是构造方法

LOCAL_VARIABLE:方法中定义的变量

ANNOTATION_TYPE:注解可以添加在注解中

PACKAGE:注解添加在包中

这部分比较简单,这里就不掩饰了,我们一般是把这7个值都设置进去(如果没有特殊要求的话)


下面来看一下注解中的定义和使用方法:

[java] view plain copy
  1. public @interface MyAnnotation{  
  2.       
  3.     String color() default "red";//属性String  
  4.     int[] value() default {1};//属性int[],这是个特殊的属性,如果只有一个value属性需要去设置值,可以不需要设置"value="  
  5.     MyEnum enums() default MyEnum.ONE;//属性enum,返回值是MyEnum枚举  
  6.     MetaAnnotation annotation() default @MetaAnnotation("red");//注解属性  
  7.     //静态常量  
  8.     boolean isRunning = false;  
  9.   
  10. }  

注解中定义的属性和接口中定义的是有区别的,注解中定义一个属性:Void fun() default ===>返回类型 属性名称 默认值,使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。当然注解中定义的类型有:注解参数的可支持数据类型:

1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)

2.String类型

3.Class类型

4.enum类型

5.Annotation类型

6.以上所有类型的数组

当然注解中也可以定义一个字段,这个字段的类型和接口中的类型是一样的,默认的是静态常量,下面来看一下注解的使用方法:

[java] view plain copy
  1. package com.annotation.demo;  
  2.   
  3. @MyAnnotation(color="red",value={1,2,3},enums=MyEnum.ONE)  
  4. public class UseAnnotation {  
  5.   
  6.     public void fun(){  
  7.     }  
  8.       
  9. }  
给属性赋值也是很简单的,直接使用“=”即可,这里要注意的是注解中有个特殊的属性,那就是value属性,我们先来看一下@Retention注解的源代码
[java] view plain copy
  1. public @interface Retention {  
  2.     RetentionPolicy value();  
  3. }  


再看一下他的使用方法:

@Retention(RetentionPolicy.SOURCE)

我们发现这个使用没有用到“=”按照常理应该是:value=RetentionPolicy.SOURCE这样使用的,所以这里value就是个特殊的属性了,名称不能写错了,是value,当一个注解中有且只有一个属性value的时候,我们可以省略"=",直接这样赋值,这里要注意是有且仅有一个,如果注解中有多个属性,这时候就不能这样操作了,像我们自定义的注解MyAnnotation中还有其他的注解,所以就不能省略"="了,当然如果你在其他的属性中在定义一个默认值就是default,这时候也还是可以省略“=”的,其他的情况就不行了


写到这里就算结束了,这个注解是很简单的,他的作用也很明白,就是标记的作用,我们需要自己顶一个注解管理器(spring中就是这样做的,这样就可以查到这个类上的所有标记了,通过这个标记在对这个类进行相应的操作)

原创粉丝点击