黑马程序员——java加强之注解

来源:互联网 发布:掷骰子抽奖js特效 编辑:程序博客网 时间:2024/05/02 02:30
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

注解

一、概述

        1、注解(Annotation)相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记。以后,javac编译器、开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。

        2、标记可以加在包,类,字段,方法,方法的参数以及局部变量上。

        3、在java.lang包中提供了最基本的注解(annotation)。

        4、格式:@注解类名。

            如果只有一个value名称的属性或其他属性缺省,则可@注解名(”属性值”);

            如果有多个或不缺省或者需重新赋值,则@注解名(属性名=”属性值”,…)。

 

二、java中三种最基本的注解

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

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

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

2、@Deprecated:表示告知调用者,该成员函数、字段等已经过时,不再推荐使用。

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

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

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

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

 

三、注解的应用结构图

      

       注解就相当于一个你的源程序中要调用的一个类,要在源程序中应用某个注解,得先准备好了这个注解类。就像你要调用某个类,得先有开发好这个类。

 

四、自定义注解及其应用

1、定义格式:@interface名称{statement}

      如:

          最简单的注解类:public@interface MyAnnotation{}

2、元注解(注解的注解)

       即在定义注解类的时候加注解。如两个常用于元注解的注解:Retention和Target

        1)Retetion:用于说明注解保留在哪个阶段(即注解的生命周期)。

       一个注解的生命周期包含:java源程序--(javac)-->class文件--(类加载器)-->内存中的字节码

         分别对应Retetion这个枚举类的值:

                RetetionPolicy.SOURSE:java源文件时期,如@Overried和@SuppressWarning

                 RetetionPolicy.CLASS: class文件时期(默认阶段)

                 RetetionPolicy.RUNTIME:运行时期,如@Deprecated

         如:在某注解类上加@Retention(RetentionPolicy.RUNTIME),表示此注解会一直存在。

注:

        1、当在源程序上加了注解,javac将java源程序编译为class文件时,会对注解的生命周期进行判断。如果该注解只保留在源程序,则编译时会将该注解进行相应的处理操作,如去掉。其他类推。

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

       

        2)Target:用于说明注解类的使用范围。如在方法上还是类上,默认值是任何地方。

       其值可设置为枚举类ElementType类中的任何一个,包括:包、字段、方法、方法参数、构造器、类等值。取值为:

                PACKAGE(包声明)

                FIELD(字段声明)

                ANNOTATION_TYPE(注释类型声明)

                 CONSIRUCTOR(构造器声明)

                METHOD(方法声明)

                PARAMETER(参数声明)

                TYPE(类、接口(包含注释类型)或枚举声明)

                LOCAL_VARIABLE(局部变量声明)

注意:其中代表类的值是TYPE。因为class、enum、interface和@interface等都是平级的,所以统属于Type。不可用CLASS表示。

3、注解的应用

       通过反射方式来获取自定义的注解类,步骤跟注解的应用结构一致,

       如:

            第一、定义注解类:@interfaceA{}

             第二、应用了“注释类”的类:@A class B{}

            第三、对“应用注释类的类”进行反射操作的类:classc{...},操作如下:

                          B.class.isAnnotionPresent(A.class);//判断是否存在此注解类

                           Aa = B.class.getAnnotation(a.class);//存在的话则得到这个注释类的对象 

示例:

package cn.itheima.Demo;

 

import java.lang.annotation.Retention;

importjava.lang.annotation.RetentionPolicy;

 

@Retention(RetentionPolicy.RUNTIME)//元注释

//注解类

public @interface MyAnnotation {

}

 

@MyAnnotation

//应用类

public class AnnotationDemo {

         @SuppressWarnings("deprecation")//此注解用于抑制过时信息的提示

         publicstatic void main(String[] args) {

                  

                   System.runFinalizersOnExit(true);//这是一个过时了的方法 ,如果没有注解就会有警告提示

                   //判断此类是否有MyAnnotation注解

                   if(AnnotationDemo.class.isAnnotationPresent(MyAnnotation.class)) {

                            //如果有,则获取该注解

                            MyAnnotationannotation =AnnotationDemo.class.getAnnotation(MyAnnotation.class);

                            System.out.println(annotation);

                   }

         }

}

五、为注解添加基本属性

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

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

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

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

              @MyAnnotation(color=”red”)

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

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

       3)用反射方式获得注解对应的实例对象后,可以通过该对象调用属性对应的方法来获取属性值。

 

六、为注解增加高级属性

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

       1)八种基本数据类型   

       2)String类型 

       3)Class类型

       4)枚举类型  

       5)注解类型  

       6)前五种类型的数组

2、数组类型的属性:

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

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

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

3、枚举类型的属性:

       假设定义了一个枚举类TrafficLamp,它是EnumTest的内部类,其值是交通灯的三色。

       定义:EnumTest.TrafficLamplamp();

       应用:@MyAnnotation(lamp=EnumTestTrafficLamp.GREEN)

4、注解类型的属性:

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

       定义:MetaAnnotationannotation() default @MetaAnnotation(”xxx”);

       应用:@MyAnnotation(annotation=@MetaAnnotation(”yyy”))//重新赋值

可以认为上面这个@MyAnnotation是MyAnnotaion类的一个实例对象,同样的道理,可以认为上面这个@MetaAnnotation是MetaAnnotation类的一个实例对象,调用代码如下:

       MetaAnnotationma =MyAnnotation.annotation();

       System.out.println(ma.value());

5、Class类型的属性:

       定义:Classcls();

       应用:@MyAnnotation(cls=AnnotationDemo.class)

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

6、注解的详细语法可通过查看java语言规范了解即javaLanguageSpecification

示例:

package cn.itheima.demo;

 

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.METHOD,ElementType.TYPE})//元注解,指定使用范围

//注解类

public @interface MyAnnotation {

         Stringcolor() default "red" ;

         Stringvalue();

         //数组

         int[]arr() default {1,2,3};

         //枚举

         EnumTest.TrafficLamplamp() default EnumTest.TrafficLamp.GREEN;

         //注解类

         MetaAnnotationannotation() default @MetaAnnotation("heima");

         //Class类

         Classclazz() default System.class;

}

 

import java.lang.reflect.Method;

 

//注解类的应用,给属性赋值或者重新赋值

@MyAnnotation(lamp=EnumTest.TrafficLamp.YELLOW,value="heima",

                            clazz=AnnotationDemo.class,annotation=@MetaAnnotation("itheima"))

//应用类

public class AnnotationDemo {

         @SuppressWarnings("deprecation")//此注解用于抑制过时信息的提示

         @MyAnnotation("Method")//自定义注解应用在方法上

         publicstatic void main(String[] args) throws NoSuchMethodException, SecurityException{

                  

                   System.runFinalizersOnExit(true);//这是一个过时了的方法 ,如果没有注解就会有警告提示

                   //判断此类是否有MyAnnotation注解

                   if(AnnotationDemo.class.isAnnotationPresent(MyAnnotation.class)) {

                            //如果有,则获取该注解

                            MyAnnotationannotation =AnnotationDemo.class.getAnnotation(MyAnnotation.class);

                            System.out.println(annotation);//@cn.itheima.Demo.MyAnnotation()

                            System.out.println(annotation.color());//red

                            System.out.println(annotation.value());//heima

                            System.out.println(annotation.arr().length);//3

                            System.out.println(annotation.lamp());//YEllOW

                            System.out.println(annotation.annotation().value());//itheima

                            System.out.println(annotation.clazz());//classcn.itheima.demo.AnnotationDemo

                   }

                  

                   //获取方法上的注解

                   MethodmainMethod=AnnotationDemo.class.getMethod("main",String[].class);

                   MyAnnotationannotationMethod=(MyAnnotation) mainMethod.getAnnotation(MetaAnnotation.class);

                   SuppressWarningssw=mainMethod.getAnnotation(SuppressWarnings.class);

                   System.out.println(sw);//null

                   System.out.println(annotationMethod);//null        

         }

}

0 0
原创粉丝点击