Java注解(Tiger)

一.    Java注解(Tiger

 

annotation type 不能够继承任何的interface annotation,包括java.lang.annotation.Annotation

所有的annotation type 都自动隐式的继承之java.lang.annotation.Annotation

 

所有显式的继承过后,所得到的type 都不在是 annotation type

 

 

1.       Tiger中内置的Annotation

a)         @Override

指示一个方法必须覆盖其父类中的一个方法,否则会出现编译器warning

作用:可以防止出现子类并没有覆盖父类的情况,例如,子类中的方法拼写错误(方法名,方法参数等)。

代码如下:

Package java.lang;  //可以直接使用,而不需导入任何包

 

@Target(ElementType.METHOD)   //只可使用在方法上

@Retention(RetentionPolicy.SOURCE)   //annotation只保持在.java文件中,//而不在.class文件中

public @interface Override {

}

 

 

b)        @Deprecated

指示一个方法已过时,不建议使用,或则已有更好的方法替代

使用或继承一个已被声明为@Deprecated的方法时,会产生警告

package java.lang;

import java.lang.annotation.*;

 

/**

 * A program element annotated @Deprecated is one that programmers

 * are discouraged from using, typically because it is dangerous,

 * or because a better alternative exists.  Compilers warn when a

 * deprecated program element is used or overridden in non-deprecated code.

 *

 * @author  Neal Gafter

 * @version 1.4, 06/10/04

 * @since 1.5

 */

@Documented    //可以在公开API中显示Annotation

@Retention(RetentionPolicy.RUNTIME)  

public @interface Deprecated {

}

:@Documented@Inherited必须和@Retention(RetentionPolicy.RUNTIME)成对使用

c)        @SuppressWarning(“unchecked”)

抑制某些不必要的编译器警告(例如:Collection中没有使用泛型)

作用:在一个完整的程序中,不应该出现任何警告。

 

 

package java.lang;

 

import java.lang.annotation.*;

import java.lang.annotation.ElementType;

import static java.lang.annotation.ElementType.*;

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})

@Retention(RetentionPolicy.SOURCE)

public @interface SuppressWarnings {

    String[] value();

}

注:@Retention(RetentionPolicy.SOURCE),所以不可以通过Reflection(反射机制)在.class文件中获得该Annotation的相关信息

 

2.     自定义的Annotation类型

a)      不需要定义一个member

package com.tyy.classTest;

 

public @interface AnnotationTest {

 

}

 

 

注:由于此处并没有提供Target,故此Annotation可以使用与任何位置

 

在需要使用的地方,只要在其定义上面加上 @com.tyy.classTest.AnnotationTest即可

 

b)      含有membersAnnotation

package com.tyy.classTest;

 

public @interface MemberAnnotation {

    String value();

}

 

注:value相当于一个成员变量,虽然其定义有点像接口中的方法定义。

但其在通过反射取值的时候,必须得通过Annotation.value()取得value属性中的值。

 

c)      members是数组或emum

package com.tyy.classTest;

 

public @interface EnumAnnotation {

    public enum EnumTest {

       hello,world,welcom;

    }

    EnumTest[] value();

}

 

 

注:在使用的时候,可以通@EnumAnnotation({EnumAnnotation.EnumTest.hello,EnumTest,world})来使用

当只有一个值的时候,可以不用大括号

 

在上述自定义的Annotation中,member也可以不使用value,那么在使用Annotation时,必须要在其使用的时候传的参数为   memberName=传的参数值

 

例如:@EnumAnnotation(memberName = EnumAnnotation.EnumTest.hello)

 

二.     四种meta-annotation

 

其定义全部位于java.lang.annotation package中,全部都只可使用在Annotation type之上

 

ElementType的代码如下:

package java.lang.annotation;

 

public enum ElementType {

    /** Class, interface (including annotation type), or enum declaration */

    TYPE,

    /** Field declaration (inlcudes enum constants) */

    FIELD,

    /** Method declaration */

    METHOD,

    /** Parameter declaration */

    PARAMETER,

    /** Constructor declaration */

    CONSTRUCTOR,

    /** Local variable declaration */

    LOCAL_VARIABLE,

    /** Annotation type declaration */

    ANNOTATION_TYPE,

    /** Package declaration */

    PACKAGE

}

 

 

 

 

 

 

1.    @Target

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)  // annotation仅适用与annotation 类型

public @interface Target {

    ElementType[] value();  //传进来的参数类型为ElementType[]类型

}

 

注: @Target annotation通常和ElementType成对使用。ElementType通常用来指定Target的所使用的元素类型,ElementTypeenum类型的。

 

如果在自定义的Annotation中不适用 @Target annotation,则该自定义的annotation适用于任何位置

 

 

2.    @Retention

package java.lang.annotation;

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Retention {

    RetentionPolicy value();

}

 

 

注: 用于指定该Annotation的保持类型。

根据RententionPolicy,可以确定该annotation是保持在source(源文件),还是在class(在.class文件中,但不被JVM读取),或是在runtime中(在.class中,在JVM第一次运行时读取)。  默认情况下的保持类型为CLASS

 

RententionPolicy的代码如下:

package java.lang.annotation;

 

public enum RetentionPolicy {

    /**

     * Annotations are to be discarded by the compiler.

     */

    SOURCE,

 

    /**

     * Annotations are to be recorded in the class file by the compiler

     * but need not be retained by the VM at run time.  This is the default

     * behavior.

     */

    CLASS,

 

    /**

     * Annotations are to be recorded in the class file by the compiler and

     * retained by the VM at run time, so they may be read reflectively.

     *

     * @see java.lang.reflect.AnnotatedElement

     */

    RUNTIME

}

 

 

注: RententionPolicy也是一个enum类型的。

 

如果是@Documented@Inherited annotation,则必须使用@RetentionRetentionPolicy.RUNTIME,以确保其可以通过class文件反射得到其中的annotation

 

3 @Documented

package java.lang.annotation;

 

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Documented {

}

 

 

注: 指定该Annotation可以通过公共的API文档反映出来

 

必须指定@RetentionRententionPolicy.RUNTIME

 

 

3.    @Inherited(可以通过Reflect机制验证)

package java.lang.annotation;

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Inherited {

}

 

 

 

注: 比较容易误解的一个annotation。用于指定一个Annotation可以被继承

 

关于@InheritedJava doc 有如下一段说明:

@Documented
      
      
@Retention(value=RUNTIME)
      
      
@Target(value=ANNOTATION_TYPE)
      
      
public @interface Inherited
      
      

Indicates that an annotation type is automatically inherited. If an Inherited meta-annotation is present on an annotation type declaration, and the user queries the annotation type on a class declaration, and the class declaration has no annotation for this type, then the class's superclass will automatically be queried for the annotation type. This process will be repeated until an annotation for this type is found, or the top of the class hierarchy (Object) is reached. If no superclass has an annotation for this type, then the query will indicate that the class in question has no such annotation.

Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class. Note also that this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect.

 

 

红色部分标记的大致含义是:在任何除class之外的地方使用该annotatio类型都是没有任何作用的。但在实验过程中,发现这段说明是有误的。

其实  如果在方法的前面使用@Inherited,依然可以被子类继承过去。

 

对于绿色部分:此元注解只能够从超类中继承注解,而从接口继承过来的都是无效的,亦即无法完成继承annotation

 

如果方法被override,则连带其父类的方法和annotation一并被override

 

注: 关于@Inherited的作用,可以通过Reflect来验证;

下面给出一个示例

InheritedTest.java

// 一个annotation

package com.tyy.inherited;

 

import java.lang.annotation.Documented;

import java.lang.annotation.Inherited;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

 

@Documented

@Inherited

@Retention(RetentionPolicy.RUNTIME)

public @interface InheritedTest {

    String value();

}

 

SuperClass.java

// 用于测试的一个父类

package com.tyy.inherited;

 

public class SuperClass {

    // 其中annotation放在了方法的上面,测试其能否被继承到子类SubClass当中。

    // 也即看看Java doc中的描述是否正确

    @InheritedTest("hello world")

    public void doSomething() {

       System.out.println("do something in superclass");

    }

}

 

SubClass.java

// 一个用于测试的子类

package com.tyy.inherited;

 

/*

 * 其中不包含任何的方法,期待着从父类中继承过来。通过反射机制,看看annotation能否被继承过来

 */

public class SubClass extends SuperClass {

 

}

 

 

Test.java

// 一个测试结果类

package com.tyy.inherited;

 

import java.lang.reflect.AnnotatedElement;

 

/**

 * 一个用来测试Subclass中通过继承而来的方法是否继承了@InheritedTest

 * @author Administrator

 *

 */

public class Test {

    public static void main(String[] args) {

       //需要进行测试的类

       Class<SubClass> c = SubClass.class;

       //通过Reflect得到其中的方法

       AnnotatedElement ae = null;

       try {

            ae = c.getMethod("doSomething", new Class[]{});

       } catch (SecurityException e) {

           // TODO Auto-generated catch block

           e.printStackTrace();

       } catch (NoSuchMethodException e) {

           // TODO Auto-generated catch block

           e.printStackTrace();

       }

      

       if(ae.isAnnotationPresent(InheritedTest.class)) {

           InheritedTest it = ae.getAnnotation(InheritedTest.class);

           String name = it.annotationType().getName();

           String value = it.value();

           //取出Annotation的包.类名和传给value的值

           System.out.println("Annotation name is " + name);

           System.out.println("value = " + value);

       }

      

    }

}

 

打印的结果为:

Annotation name is com.tyy.inherited.InheritedTest

value = hello world

 

注意:这里打印的结果没有为空,而是确实打印出了结果,可以看到当使用@Inherited 注解的注解类型运用于方法时,也会起作用,所以可以看到Java doc在这方面的描述确实是有误的。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值