Java 基础加强 - JDK1.5新特性 - 注解

来源:互联网 发布:Linux 13位密码破解 编辑:程序博客网 时间:2024/05/18 20:48

Java基础加强 - 注解

一.注解的定义

定义: 注解(Annotation)是一种标记性的接口,注解是Java的一个新的类型(与接口很相似),它与类(Class)、接口(interface)、枚举(enum)是在同一个层次,注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记。我们可以定义注解、声明注解、获得注解,并且根据获得的注解做相应的处理,许多框架都大量应用了注解。

 

二.对于java.lang.Annotation的理解

1.   所有定义的注解类型到会继承该Annotation接口,定义注解需要使用@interface。

2.   注解声明个格式:

权限修饰符@interface注解类名{}

以下为定义了一个注解MyAnnotation:

public @interface MyAnnotation{}

3.   注解定义好后,可以使用在包、类、字段、方法和方法的参数上以及局部变量上。

4.      当我们使用@interface关键字定义一个注解时,该注解隐含地继承了java.lang.annotation.Annotation接口;如果我们定义了一个接口,并且让该接口继承自Annotation,那么我们所定义的接口依然还是接口而不是注解;Annotation本身是接口而不是注解。可以与Enum类比。

 

 

三.        为注解添加基本属性

1.    属性: 一个注解相当于一个胸牌,但仅通过胸牌还不足以区别带胸牌的两个人,这时就需要给胸牌增加一个属性来区分,如颜色等。

2.    定义格式: 同接口中的方法一样:Stringcolor();

定义缺省格式: String value()default “heima”;

3.     应用: 直接在注解的括号中添加自身的属性,如:

              @MyAnnotation(color=”red”)

4.     如果注解中有一个名称为value的属性,且你只想设置value属性(即其他属性都采用默认值或者你只有一个value属性),那么可以省略value=部分,例如: @SuppressWarnings("deprecation")。

5.     可以为属性值指定缺省值(default),应用时同样可以重新设置属性值。

四. 为注解增加高级属性

1.     可以为注解增加高级属性的返回值类型有:

A.    八种基本数据类型

B.     String类型

C.     Class类型

D.    枚举类型

E.     注解类型

F.      前五种类型的数组

2.   数组类型的属性

  如: int[]arrayArr()default {1,2,3};//可不定义默认值

应用: @MyAnnotation(arrayArr={2,3,4}) //可重新赋值

注: 若数组属性中只有一个元素(或重新赋值为一个元素),这时属性值部分可省略大括号。

public @interface MyAnnotation{    int[] array() ;    int[] array2() default {1,2,3};    int[] array3() default 2;}

3.   枚举类型的属性

定义:

public @interface MyAnnotation{    int[] array() ;    int[] array2() default {1,2,3};    int[] array3() default 2;Color color();//枚举属性EnumTest. TrafficLamp lamp() default EnumTest. TrafficLamp. RED }

应用:

@MyAnnotation(lamp=EnumTest.TrafficLamp.BLUE,array={2,3,4},color=Color.BLACK)

4.     注解类型的属性
假定有个注解类:MetaAnnotation,其中定义了一个属性:Stringvalue()

定义: MetaAnnotation annotation() default @MetaAnnotation(”xxx”);
应用:@MyAnnotation(annotation=@MetaAnnotation(”yyy”))//可重新赋值

注意:可认为上面的@MetaAnnotation是MyAnnotation类的一个实例对象,同样可以认为上面的@MetaAnnotation是MetaAnnotation类的一个实例对象,调用:MetaAnnotationma =MyAnnotation.annotation();
System.out.println(ma.value());

5.     Class类型的属性

定义:

public @interface MyAnnotation{    int[] array() ;    int[] array2() default {1,2,3};    int[] array3() default 2;    Color color() default Color.BLACK;    Class clazz();//定义一个Class类型属性}

应用:

@MyAnnotation(array={2,3,4},clazz = WeekdayTest.class)

注意:这里的.class必须是已定义的类,或是已有的字节码对象

6.   基本数据类型的属性(以int为例):

定义:

public @interface MyAnnotation{    int[] array() ;    int[] array2() default {1,2,3};    int[] array3() default 2;    Color color() default Color.BLACK;    Class clazz();    int val();//定一个基本数据类型的属性}

应用:

@MyAnnotation(array={2,3,4},clazz = WeekdayTest.class, val=3)

五.        Java中三种基本的注解

 

1.      @SuppressWarning(”deprecation”): 表示压制过时警告;或者说不要警告过时提示了

        SupressWarning是告知编译器或开发工具等不需要再提示指定的警告了;

        “deprecation”是警告的信息,即过时警告。

2.      @Deprecated: 表示告知调用者,该成员函数、字段等已经过时,不再推荐使用。源代码标记@Deprecated是在JDK1.5中作为内置的annotation引入的,用于表明类(class)、方法(method)、字段(field)已经不再推荐使用,并且在以后的JDK版本中可能将其删除,编译器在默认情况下检测到有此标记的时候会提示警告信息。

例如: 假定之前的某个类升级了,其中的某个方法已经过时了,不能够将过时的方法删除,因为可能会影响到之前调用此这个方法的某些程序,这时就可以通过在方法上加这个注解来标记。

3.      @Override: 表示下面的方法是在覆盖父类方法,如果不存在覆盖,就会报错。

加上此注解,可对类中的方法判断是否是要覆盖的父类的方法。典型的例子即在类中覆盖equals(Object obj)方法时,其中的参数类型必须是Object,才能被覆盖;若不是,则不存在覆盖。此时如果加上了此注解就会提示警告。

 

六.        注解应用结构图

 

七.        元注解(注解的注解)

1.    作用:

元注解的作用是在自定义注解的时候使用元注解,元注解,这些元注解的值被定义后,可以告诉这个注解是保留在什么阶段,如编译器,运行期,等等,还可以告诉注解知道是用在什么目标上,比如只能用在方法上,只能用来类上,等等。

2.    使用元注解定义注解,元注解有四种:

A.   @Target(ElementType.[type])
[type]={METHOD, FIELD, TYPE(类、接口、枚举声明), CONSTRUCTOR, LOCAL_VARIABLE,PARAMETER}

B.  @Retention(RetentionPolicy.[policy])
[policy]={SOURCE(源文件时期), CLASS(Class文件时期,默认阶段), RUNTIME(运行时期,反射机制可读取,@Deprecated)}

一个注解的生命周有如下几个状态:

java源程序--(javac)-->class文件--(类加载器)-->内存中的字节码

第一.       当一个注解加上@Retention(RetentionPolicy.SOURCE)注解后,javac将java源程序编译为class文件,可能会把源程序中的一些注解去掉,进行相应的处理操作,当我们拿到源程序的时候,就看不到这些注解了。

第二.       当一个注解加上@Retention(RetentionPolicy. CLASS)注解后,假设javac把这些注解留在了源程序中(或者说留在了class文件中),当运行此class文件的时候,用类加载器将class文件调入内存中,此时有转换的过程,即把class文件中的注解是否保留下来也不一定。

第三.       当一个注解加上@Retention(RetentionPolicy. RUNTIME)注解后,说明这个注解会保留到运行时期,在运行时期我们可以通过反射去获取注解信息,其中代表类的值是TYPE。因为classenuminterface@interface等都是属于Type的。不可用CLASS表示。

注意: class文件中不是字节码,只有把class文件中的内部加载进内存,用类加载器加载处理后(进行完整的检查等处理),最终得到的二进制内容才是字节码。

C.  @Documented 表示将此注解包含到Javadoc中

D.  @Inherited 表示允许子类继承父类的注解

八.        练习

@MyAnnotation(array={2,3,4},clazz = EnumTest.class, val=3)public class EnumTest{@MyAnnotation(val = 24)public static void main(String[] args){      if(EnumTest.class.isAnnotationPresent(MyAnnotation.class))           {           MyAnnotation annotion = EnumTest.class.getAnnotation(MyAnnotation.class);           System.out.println(annotion);           System.out.println(annotion.val());           System.out.println(annotion.array());           System.out.println(annotion.array2());           System.out.println(annotion.array3());           System.out.println(annotion.clazz());           System.out.println(annotion.color());           }}}import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;//将注解保留到运行期@Retention(RetentionPolicy.RUNTIME) })//将注解作用在方法和类上@Target({ElementType.TYPE,ElementType.METHODpublic @interface MyAnnotation{    int[] array() default 25 ;    int[] array2() default {1,2,3};    int[] array3() default 2;    Color color() default Color.BLACK;    Class clazz() default Color.class;    int val();}public enum Color{     RED,BLUE,BLACK}