java 新特性 ----Annontation (8)

来源:互联网 发布:e宠商城淘宝店 编辑:程序博客网 时间:2024/05/29 16:16


一、概念
j2se 提供了很多新特性。其中一个很重要的特性就是对元数据(Metadata)的支持。在j2se 5.0 中,这种数据被称为注释(Annontation).通过使用注释,程序开发人员可以在不改变原有逻辑的情况下,在源文件嵌入一些补充的信息。
Annontation 可以用来修饰类、属性、方法,而且Annontation 不影响程序运行,无论是否使用Annontation 代码都可以正常运行。
Java.lang.annontation.Annontation 是Annontation 的接口,只要是Annontation 都必须实现此接口。此接口定义如下:

public interface Annontation{    public Class<? extends Annontation> annotationType();    public boolean equals(Object obj) ;    public int hashCode();    String toString();}

二、原理
  Annotation其实是一种接口。通过Java的反射机制相关的API来访问annotation信息。相关类(框架或工具中的类)根据这些信息来决定如何使用该程序元素或改变它们的行为。
  annotation是不会影响程序代码的执行,无论annotation怎么变化,代码都始终如一地执行。
  Java语言解释器在工作时会忽略这些annotation,因此在JVM中这些annotation是“不起作用”的,只能通过配套的工具才能对这些annontaion类型的信息进行访问和处理。
  Annotation与interface的异同:
    1)、Annotation类型使用关键字@interface而不是interface。
  这个关键字声明隐含了一个信息:它是继承了java.lang.annotation.Annotation接口,并非声明了一个interface
    2)、Annotation类型、方法定义是独特的、受限制的。
  Annotation类型的方法必须声明为无参数、无异常抛出的。这些方法定义了annotation的成员:方法名成为了成员名,而方法返回值成为了成员的类型。而方法返回值类型必须为primitive类型、Class类型、枚举类型、annotation类型或者由前面类型之一作为元素的一维数组。方法的后面可以使用default和一个默认数值来声明成员的默认值,null不能作为成员默认值,这与我们在非annotation类型中定义方法有很大不同。
  Annotation类型和它的方法不能使用annotation类型的参数、成员不能是generic。只有返回值类型是Class的方法可以在annotation类型中使用generic,因为此方法能够用类转换将各种类型转换为Class。
    3)、Annotation类型又与接口有着近似之处。
  它们可以定义常量、静态成员类型(比如枚举类型定义)。Annotation类型也可以如接口一般被实现或者继承。

三、应用场合
annotation一般作为一种辅助途径,应用在软件框架或工具中,在这些工具类中根据不同的annontation注解信息采取不同的处理过程或改变相应程序元素(类、方法及成员变量等)的行为。
例如:Junit、Struts、Spring等流行工具框架中均广泛使用了annontion。使代码的灵活性大提高。

四、常见使用方法
1、系统内间的Annontation 类型:
    @Override:覆写的Annontation;
    @Deprecated:不赞成使用的 Annontation ;
    @SuppressWarnings:压制安全警告的Annontation.
1.1、@Override 主要是在方法覆写时使用,用于保证覆写的正确性。
@Override 注释的作用:
代码:
package com.zsc.annon;public class OverrideAnnontationTest {    public static void main(String[] args) {        Person per = new Student();        System.out.println(per.getInfo());    }}class Person{    public String getInfo(){        return "这是一个Person类";    }}class Student extends Person{    @Override    public String getInfo(){        return "这是一个Student类";    }}

错误的覆写:
package com.zsc.annon;public class OverrideAnnontationTest {    public static void main(String[] args) {        Person per = new Student();        System.out.println(per.getInfo());    }}class Person{    public String getInfo(){        return "这是一个Person类";    }}class Student extends Person{    @Override    public String getiInfo(){    // 提示错误        return "这是一个Student类";    }}

注意:@Override 使用限制。
@Override 在使用时只能在方法上使用,而其他元素,如类、属性等上面是不可以使用的。

2、@Deprecated
@Deprecated 注释的主要功能是用来声明一个不建议使用的方法。如果在程序中使用了此方法,则在编译时将出现警告信息。

使用 @Deprecated 生命一个不建议使用的方法:
代码:
package com.zsc.annon;public class DeprecatedAnnontationTest {    public static void main(String[] args) {        Person per = new Person();        System.out.println(per.getInfo());    }}class Persons{    @Deprecated    public String getInfo(){        return "这是一个Persons类";    }}

3、@SuppressWarnings
@SuppressWarnings 注释的主要功能是用来压制警告,例如,如果在一个声明时没有指明泛型,则肯定会编译时产生,那么此时就可以使用@SuppressWarnings 压制这种警告。
压制一个警告:
代码:
package com.zsc.annon;public class SuppressWarningsAnnontationTest {    @SuppressWarnings("unchecked")    public static void main(String[] args) {        Personss per = new Personss();        per.setVar("张三");        System.out.println("内容:"+per.getVar());    }}class Personss<T>{    private T var ;    public T getVar(){        return var ;    }    public void setVar(T var){        this.var = var ;    }}

4、自定义Annontation
4.1、定以简单的Annontation
格式 [public] @interface Annontation名称{
    数据类型 变量名称();
}
要定以 Annontation 必须使用 @interface 的方式进行定义,在定义Annontation 时也可以定以各种变量,但是变量定义之后必须用“()”。
自定义一个 Annontation
代码:
package com.zsc.annon;public @interface AnnontationTest {}

4.2 向Annontation 中设置内容:
定义MyAnnontation ,可以接受一个变量
代码:
package com.zsc.annon;public @interface MyAnnontation {    public String value() ;}

在以上的Annontation 中定义了一个value ,在以后使用此 Annontation时,可以将内容设置给value .
向Annontation 中设置内容:
代码:
@MyAnnontation("张三")class Demo{    }

在使用@MyAnnontation 时也可以直接指定接受的参数的属性名称。
代码:
@MyAnnontation(value="张三")class Demo{    }

在@MyAnnontation 中设置多个属性:
代码:
package com.zsc.annon;public @interface MyAnnontation {    public String key();    public String value() ;}

分别设置内容:
@MyAnnontation(value="张三",key="学生")class Demo{    }

在@MyAnnontation 设置数组属性
代码:
package com.zsc.annon;public @interface MyAnnontation {    public String[] value();    }

设置一个数组:
@MyAnnontation(value={"张三","学生"})class Demo{    }

4.3、默认值
如果在一个已经定义好的Annontation 中已经定义了若干属性,但是在使用Annontation 时并没有制定具体的内容,则在编译时也会出现错误。此时可以使用默认值。
格式:[public] @interface Annontation名称{
    数据类型 变量名称() dafault 默认值;
}
定以一个存在默认值的Annontation
代码:
package com.zsc.annon;public @interface MyAnnontation {    public String key() default "学生";    public String value() default "张三";}

这样的话,在以后调用MyAnnontation 时候没有设置内容,则会将默认值赋给属性,而如果已经明确的给出了内容,则将给出的内容赋给属性。

4.4、通过反射取得 Annontation
如果要让一个Annontation 起作用,则必须结合反射机制。
4.4.1 取得全部的 Annontation
代码:
package com.zsc.annon;public class SimpleDemo {    @Override    @SuppressWarnings(value="unchecked")    @Deprecated    public String toString(){        return "hello everyone!" ;    }}

代码2:
package com.zsc.annon;import java.lang.annotation.Annotation;import java.lang.reflect.Method;public class ReflactTest {    public static void main(String[] args) throws Exception {        Class<?> c = null ;        c = Class.forName("com.zsc.annon.SimpleDemo");        Method mt = c.getMethod("toString");        Annotation an[] = mt.getAnnotations();        for(Annotation a:an){            System.out.println(a);        }    }}

运行结果:
@java.lang.Deprecated()

SimpleDemo 的toString() 方法虽然使用了3个Annotation 注释,但是最后真正得到的只能是一个,这是因为只有Deprecated 使用了 RUNTIME 的方式声明,所以只有它可以取得。

4.4.2 取得指定的Annotation 中的内容
代码1:
package com.zsc.annon;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;@Retention(value=RetentionPolicy.RUNTIME)public @interface MyAnnotationReflact {    public String key() default "student";    public String value() default "zhangsan";}

代码2:
package com.zsc.annon;public class SimpleDemo2 {    @Override    @Deprecated    @SuppressWarnings("unchecked")    @MyAnnotationReflact(key="worker",value="lisi")    public String toString(){        return "hello word !";    }}

代码3:
package com.zsc.annon;import java.lang.reflect.Method;public class ReflactTest2 {    public static void main(String[] args) throws Exception {        Class<?> c = null ;        c = Class.forName("com.zsc.annon.SimpleDemo2");        Method mt = c.getMethod("toString");        if(mt.isAnnotationPresent(MyAnnotationReflact.class)){            MyAnnotationReflact mda = null ;            mda = mt.getAnnotation(MyAnnotationReflact.class);            String key = mda.key();            String value = mda.value();            System.out.println("key:"+key);            System.out.println("value:"+value);        }    }}

运行结果:
key:workervalue:lisi

总结:从上面可以看到,只要适当的使用反射机制,就可以将Annotation中指定的内容设置到对应的操作中。





原创粉丝点击