java总结(18)注解

来源:互联网 发布:知乎如何匿名提问 编辑:程序博客网 时间:2024/05/18 19:18


什么是注解

1.注解是 jdk1.5 的新特性

注解就相当于标签,给什么什么加上注解就相当于给什么什么贴上标签,这个标签在 编译、加载、JVM 执行的某个阶段可以读出来使用,判断加标签元素的具有某方面的属性。因为标签这种东西仍然可以是对象,所以在 java 里面,注解定义的源字节码加载到 JVM 后对应一个 Class 对象,使用注解的地方,是一个该注解类型的对象。但是注解对象是一种特殊的对象,它是用来修饰 包、类、成员方法、成员变量、注解 等 Class 成员的对象。并且如果想要在我们程序中引用这种对象,只能通过注解对象修饰过的类的 Class 对象来获取。注解对象仍然是一个 Object 的对象,这说明注解类型 extends Object。

Annotation(注解)是JDK5.0及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,执行基本编译时检查。注解是以‘@注解名’在代码中存在的,根据注解参数的个数,我们可以将注解分为:标记注解、单值注解、完整注解三类。它们都不会直接影响到程序的语义,只是作为注解(标识)存在,我们可以通过反射机制编程实现对这些元数据(用来描述数据的数据)的访问。另外,你可以在编译时选择代码里的注解是否只存在于源代码级,或者它也能在class文件中出现,或者它还可以再运行时中存在。

2.java提供的几个基本注解

@SurPpressWarnings 告诉编译器废弃警告
@Deprecated 告诉编译器那个成员过时了
@Override 告诉编译器这是在实现函数重载

上面三个基本注解在java.lang包。

public class AnnotationDemo {        /**       * @method: main      * @description: TODO      * @param args      * @return: void      * @author: vivianZhao      * @date: 2013-7-22 下午3:43:14      * @version: 1.0      */      @SuppressWarnings("deprecation")      public static void main(String[] args) {          // TODO Auto-generated method stub          System.runFinalizersOnExit(true);                }            @Deprecated      public static void printHello() {          System.out.println("Hello World");      }            @Override      public String toString(){          return null;      }    }  

注解的应用:




1.自定义注解及其应用:


定义一个最简单的注解:public @interface MyAnnotation {}
把它加在某个类上:@MyAnnotation public class AnnotationTest{}
用反射进行测试AnnotationTest的定义上是否有@MyAnnotation 
根据发射测试的问题,引出@Retention元注解的讲解,其三种取值:RetetionPolicy.SOURCE、RetetionPolicy.CLASS、RetetionPolicy.RUNTIME;分别对应:java源文件-->class文件-->内存中的字节码。
思考:@Override、@SuppressWarnings和@Deprecated这三个注解的属性值分别是什么?

1.@Target 元注解


Target的默认值为任何元素,设置Target等于ElementType.METHOD,原来加在类上的注解就报错了,改为用数组方式设置{ElementType.METHOD,ElementType.TYPE}就可以了。
元注解以及其枚举属性值不用记,只要会看jdk提供那几个基本注解的API帮助文档的定义或其源代码,按图索骥即可查到,或者直接看java.lang.annotation包下面的类。

2.为注解增加基本属性:


什么是注解的属性
一个注解相当于一个胸牌,如果你胸前贴了胸牌,就是传智播客的学生,否则,就不是。如果还想区分出是传智播客哪个班的学生,这时候可以为胸牌在增加一个属性来进行区分。加了属性的标记效果为:@MyAnnotation(color="red")

3.定义基本类型的属性和应用属性:


在注解类中增加String color();
@MyAnnotation(color="red")
用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法
MyAnnotation a = (MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);
System.out.println(a.color());
可以认为上面这个@MyAnnotation是MyAnnotaion类的一个实例对象

4.为属性指定缺省值:


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

5.为注解增加高级属性:


数组类型的属性
int [] arrayAttr() default {1,2,3};
@MyAnnotation(arrayAttr={2,3,4})
如果数组属性中只有一个元素,这时候属性值部分可以省略大括
枚举类型的属性
EnumTest.TrafficLamp lamp() ;
@MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN)
注解类型的属性:
MetaAnnotation annotationAttr() default @MetaAnnotation("xxxx");
@MyAnnotation(annotationAttr=@MetaAnnotation(“yyy”) )
可以认为上面这个@MyAnnotation是MyAnnotaion类的一个实例对象,同样的道理,可以认为上面这个@MetaAnnotation是MetaAnnotation类的一个实例对象,调用代码如下:
MetaAnnotation ma =  myAnnotation.annotationAttr();
System.out.println(ma.value());
注解的详细语法可以通过看java语言规范了解,即看java的language specification。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------

注解实例

1.自定义一个简单的注解


/** * 需求:自定义一个注解类型 */public @interface MyAnnotation {}

< style="margin:0px; padding:0px; line-height:26px">

2.把这个注解用在某个类上面

@MyAnnotation // 这就相当于使用自定义的注解类型,在 Class 解析的时候可以把这解析为注解对象  public class MyAnnotationTest {        public static void main(String[] args) {          // TODO Auto-generated method stub        }    }  
< style="margin:0px; padding:0px; line-height:26px">

3.使用反射获取这个注解

@MyAnnotation  // 这就相当于使用自定义的注解类型,但在 Class 解析的时候可以把这解析为注解对象  public class MyAnnotationTest {        public static void main(String[] args) {          // TODO Auto-generated method stub          // 判断某个类的修饰中是否存在 某个 Annotation 修饰          if (MyAnnotationTest.class.isAnnotationPresent(MyAnnotation.class)) {              // 如果存在该 Annotation 修饰,那么获取该 Annotation 的对象,跟获取 Method、Feild 对象一样              MyAnnotation myAnnotationObject = (MyAnnotation)MyAnnotationTest.class                      .getAnnotation(MyAnnotation.class);              System.out.println(myAnnotationObject);          }      }    }  

打印结果啥都没有,说明 JVM 判断这个类的修饰中不存在某个 MyAnnotation 修饰,主要原因是 Annotation 是有生命周期的,默认都只存在于 编译阶段,生命周期使用元注解 @Retention 来表示,在 MyAnnotation 的定义上使用 @Retention(value = RetentionPolicy.RUNTIME),或者  @Retention(RetentionPolicy.RUNTIME) 修饰之后,打印结果为:
@cn.itcast.annocation.MyAnnotation()    

cn.itcast.annocation为所在的包名。

< style="margin:0px; padding:0px; line-height:26px">

4为注解增加各种类型的属性

1.添加属性之后的 MyAnnotatin
@Retention(value = RetentionPolicy.RUNTIME)  public @interface MyAnnotation {      String color();       // 注解的属性的声明和接口的方法的声明格式差不多,我认为注解的属性声明好比是类中 getter setter 和属性声      // 明的简写形式  }  

2.在类上使用有属性的注解和用反射获取有属性注解的属性值
/**  * 需求:演示在类上使用有属性的注解和用反射获取有属性注解的属性值  */  @MyAnnotation(color = "blue")  // 这就相当于使用自定义的注解类型,但在 Class 解析的时候可以把这解析为注解对象  public class MyAnnotationTest {        public static void main(String[] args) {          // TODO Auto-generated method stub          // 判断某个类的修饰中是否存在 某个 Annotation 修饰          if (MyAnnotationTest.class.isAnnotationPresent(MyAnnotation.class)) {              // 如果存在该 Annotation 修饰,那么通过 Class 反射获取该 Annotation 的对象,跟获取 Method、Feild 对象一样              MyAnnotation myAnnotationObject = (MyAnnotation)MyAnnotationTest.class                      .getAnnotation(MyAnnotation.class);              // 使用该 Annotation 对象              System.out.println(myAnnotationObject.color());          }      }  }  

打印结果:blue

总结:注解是一种特殊的类,注解相当于是一种标记,加了注解等于打上了某种标记,没加,就没有某种标记,javac 进行编译器、开发工具和其他程序可以通过反射来了解你的类及其各种元素上的注解这种属性,并根据注解这种属性做相应的操作。注解这种标记可以加载 包、类、字段、方法、方法的参数以及局部变量上。


原创粉丝点击