Java注解的使用

来源:互联网 发布:浏览器打开淘宝很卡 编辑:程序博客网 时间:2024/05/29 13:53

简介:注解就是程序的标注,利用反射解析到这些标注可以明确应用需要做什么事情

注解的语法比较简单,除了@符号的使用之外,它基本与Java固有语法一致。Java SE5内置了三种标准注解:

 @Override,重写的注解,只能在方法上使用。 @Deprecated,用于声明不建议使用的方法,可以作用在类和方法上。 @SuppressWarnings,用于压制编译器警告。

上面这三个注解我们在进行方法重写,使用过时方法,定义集合没有给定具体泛型类型时会遇到,

除此之外Java还提供了4个注解,用于自定义注解,如下:

@Target

定义注解的使用位置

ElementType参数有:

CONSTRUCTOR:只能用在构造方法上

FIELD:只能用在字段和枚举常量上

LOCAL_VARIABLE:只能用在局部变量上

METHOD:只能用在方法上

PACKAGE:只能用在包上

PARAMETER:只能用在参数上

TYPE:只能用在类、接口、枚举类型上

@Retention

定义注解的保存范围。

RetentionPolicy参数包括:

SOURCE:只会保留在.java源文件中,不会保留在编译好的.class文件中

CLASS:会保留在.java和.class文件中,但不会被加载到JVM机,
如果声明Retention没有指定RetencationPolicy取值范围,默认是CLASS

RUNTIME:会保留在.java和.class文件中,执行时也会被加载到JVM中,常用的一种方式,因为通过反射可以获取到。

@Document

用于生成doc文档

@Inherited

标注该注解是否可以被继承,如果没有标注默认是不能被继承

public @interface MyAnnotation {  //正确定义变量的方式  public String value();    //错误定义变量的方式,编译会提示Annotation attributes cannot have parameters  public String value1(String value);   //错误定义变量的方式,编译会提示Syntax error on token "throws", default expected  public String value2()throws Exception; }
 使用自定义注解:
//使用自定义注解并给value设置内容@MyAnnotation(value = "HG")       public class TestMyAnnotation {}

在注解中设置多个变量

public @interface RequestMapping {  public String value();    public String method();}

为注解中多个变量设置内容

@RequestMapping(value="login",method="GET")  public class TestRequestMappin {}

在注解中定义数组变量

public @interface MyAnnotationArray {  public String[] value();}

为注解中的数组设置内容

@MyAnnotationArray(value={"我是一个吃货","好巧啊我也是,要不你请我辣条呗"})public class TestMyAnnotationArray {}

默认值:在进行自定义注解时,如果注解中定义了变量,但是在实际使用中没有为其赋值,编译器就会出现错误,如下

@RequestMapping public class TestRequestMappin {}

以上在编译时就会出现The annotation @RequestMapping must define the attribute value,也就是说只要在定义
注解时声明了变量,那么在使用时必须为其赋值,所以有时候为了方便使用,也可以在定义注解变量时就指定默认值

public @interface RequestMapping {  public String value() default "login.do";   //设置默认值  public String method() default "GET";       //设置默认值}

以上是为了在使用注解时,如果没有设置内容,就会将默认值赋给变量,如果明确给出了内容就会覆盖默认值。

使用枚举限制设置的内容

使用枚举限制设置的内容public enum MyEnum{  //定义枚举  DRAGON,WARDRAGON,HG;}public @interface MyAnnotationEnum {  /**    * 变量的返回类型是一个枚举,那么在为这个变量设置内容的    * 时候只能设置枚举中的内容     */  public MyEnum enums() default MyEnum.DRAGON;   }

使用MyAnnotation

//错误的设置内容,会提示Type mismatch: cannot convert from String to MyEnum@MyAnnotationEnum(enums="呵呵") //正确的设置内容@MyAnnotationEnum(enums=MyEnum.DRAGON)  public class TestMyAnnotationEnum {}

Retention:Retention中定义了一个RetentionPolicy主要是来指定注解的保存范围

使用Retention

/**  * 该注解在.class中有效,也就是存在于JVM中,可以通过反射的getAnnotations()获取  */@Retention(value=RetentionPolicy.RUNTIME)  public @interface myRetention {  public String name() default "我喜欢吃猪耳朵!";}

利用反射获取到注解:使用JDK1.5提供的@Override、@Deprecated、@SuppressWarnings

public class ReflectAnnotationDemo {    @Override  //SOURCE     @Deprecated //RUNTIME    @SuppressWarnings("unchecked") //SOURCE    public String toString() {        return "我是一个吃货";    }}

获取方法上声明的所有注解

public class ReflectDemo01 {  /**    *  反射:运行时动态获取类内部的信息    *      *  注解的声明有三种,分别是:SOURCE、CLASS、RUNTIME只有RUNTIME是存在于JVM中的    *  所以利用反射只能拿到RUNTIME声明的注解    */  public static void main(String[] args)throws Exception{    Class<?> c = Class.forName("com.dragon.Ann.ReflectAnnotationDemo");     Method toM = c.getMethod("toString");     Annotation[] ann = toM.getAnnotations();    for(Annotation a : ann){        System.out.println(a);    }  }}

以上就通过反射取到了java.lang.Deprecated,是因为只有该类的使用了RetentionPolicy.RUNTIME进行声明,所以只有他可以取到

利用反射获取自定义注解的内容

//定义存在于JVM中的注解@Retention(RetentionPolicy.RUNTIME)public @interface RequestMapping {  public String value();     public String method();       }
//使用RequestMapping注解public class TestRequestMappin {  @RequestMapping(value="login",method="GET")  public String test(){    return "我是一顿八碗饭的帅哥!";  }}
//获取指定的注解public class ReflectDemo02 {    public static void main(String[] args) throws Exception {        Class cl = Class.forName("com.dragon.Ann.TestRequestMapping");        Method toM = cl.getMethod("test");        if (toM.isAnnotationPresent(RequestMapping.class)) {//判断注解是否存在            // 取得指定注解            RequestMapping ann = toM.getAnnotation(RequestMapping.class);            System.out.println("value="+ann.value());            System.out.println("method="+ann.method());        }    }}

以上三个程序是从定义注解、使用注解、通过反射获取方法上声明的注解,其实只要适当的利用好反射,就可以将指定的内容设置到对应的操作中,这些操作在Spring中经常用到

      Target:Target中定义了一个ElementType枚举变量,主要指定注解的使用位置

定义注解

@Target({ElementType.TYPE})  //可以在类、接口、枚举上使用public @interface MyTargetAnnotation {  public String key() default "吃饭了吗";  public String value() default "吃了八碗";}

使用注解

@MyTargetAnnotation  //在类上使用,无编译错误public class TargetDemo{   @MyTargetAnnotation  //在方法上使用,编译错误   public String toString(){     return "我喜欢吃猪耳朵";   } }

如果希望定义的注解在类和方法上都可以使用,可以将注解声明为@Target({ElementType.TYPE,ElementType.METHOD}),括号中有{}括起来,表示在类和方法上都可以使用
Documented:用于生成DOC文档
定义注解

@Documentedpublic @interface MyDocumentedAnnotation {  public String key();  public String value();}

使用注解

@MyDocumentedAnnotation(key = "HG", value = "胡歌")public class DocumentedDemo {    /**      * 你好啊 大胡哥      */    @MyDocumentedAnnotation(key = "HG", value = "胡歌")    public String getHG() {        return "你好 胡歌";    }}要生成doc文档需要进入命令行中执行:javadoc -d doc DocumentedDemo,然后就会在其目录下产生一个doc文件               Inherited:标注该注解是否可以被继承,默认是不能被继承  定义注解

@Retention(value=RetentionPolicy.RUNTIME)
public @interface MyInheritedAnnotation {
public String name();
}

使用注解

@MyInheritedAnnotation(name=”HG”)
public class Person {

}

public class InheritedReflectDemo {  public static void main(String[] args)throws Exception{    Class<?> c = Class.forName("com.dragon.inherited.Student");    Annotation[] ann = c.getAnnotations();    for(Annotation a : ann){        //打印所有注解,如果注解上没有声明@Inherited则获取不到,默认是没有继承的        System.out.println(a);       }}}

上面这个例子是通过反射验证是否被继承

1 0
原创粉丝点击