黑马程序员---Java注解

来源:互联网 发布:深入理解大数据 代码 编辑:程序博客网 时间:2024/05/21 11:20

---------------------- Android培训、java培训、期待与您交流! ----------------------      

         从JDK5之后开始支持注解(Annotation),可以在Java原始码中使用注解,对编译程序提供额外编译提示,或提供应用程序执行时期可读取的状态信息。注解可以仅用Java原始码中,编译后留在.class文件仅供编译程序读取或开放执行时期读取。

常用标准注解

@Override   它跟在一个方法的上面,代表此方法是重写父类或者接口的方法。

@Deprecated   表示已经过时了的方法、类或者其它属性。

@SuppressWarnings(value={"unchecked"})  如果不想看到如同unchecked这样警告,可以改变value的值。

◆【总结】
       注解相当于一种标记,加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其它程序可以用反射来了解你的类即各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。看java.lang包,可看到JDK中提供的最基本的annotation。一个注解就是一个类,加一个注解就是创建这个注解类的一个实例对象,那么我们是不是可以自己创建注解。。。

 自定义注解

      每个注解都会有个注解类型,所有注解类型其实都是java.lang.annotation.Annotation子接口,@Override的注解类型为java.lang.Override,@Deprecated的注解类型的为java.lang.Deprecated.注解类就相当于一个你的源程序中要调用的一个类,要在源程序中应用某个注解,得先准备好了这个注解类。就像你要调用某个类,得先有开发好这个类。

定义一个最简单的注解

package com.xy.annotation;public @interface MyAnnotation{}

把它加在某个类上:

package com.xy.annotation;@MyAnnotationpublic class AnnotationTest{}

用反射进行测试AnnotationTest类的定义上是否有@MyAnnotation。

if(AnnotationTest1.class.isAnnotationPresent(MyAnnotation.class)){MyAnnotation annotation = AnnotationTest1.class.getAnnotation(MyAnnotation.class);System.out.println(annotation);
结果控制台上什么都没打印,那就是说if语句返回了FALSE,不是明明在AnnotationTest类上加了@MyAnnotation注解了么,为什么会显示没有呢?

那么我们再在自定义注解类的上方加上一个注解@Retention(RetentionPolicy.RUNTIME),再次去运行AnnotationTest类,结果控制台上打印出了结果:@com.xy.annotation.MyAnnotation()。那这是为什么呢,@Retention(RetentionPolicy.RUNTIME)这个注解怎么有这么大的神效,它是做了什么,为什么刚才没结果呢,加上它就有结果了呢?

【分析】

那我们就分析一下,出现中结果,会有两种可能。第一种可能,java编译器把java源程序编译成class文件时就把@MyAnnotation注解给去掉了;第二种可能,jvm将class文件加载到内存的过程中就把@MyAnnotation注解给去掉了。到底是哪种可能呢?但这么一分析,发现注解实际上有三个生命阶段,Java源文件-->class文件-->内存中的字节码。奥,似乎明白了,那个有神效的注解@Retention(RetentionPolicy.RUNTIME)是不是就是控制了注解类使用时的生命周期呀!!!

       @Retention()这个注解其实有三个属性,RetetionPolicy.SOURCE、RetetionPolicy.CLASS、
RetetionPolicy.RUNTIME,分别表示注解的生命周期在源代码阶段,在编译成class阶段,在运行阶段。它的默认属性是RetetionPolicy.CLASS。

【总结】

原来最初控制台没有打印结果是因为@MyAnnotation注解在编译阶段就被去掉了,所以用反射透析是找不到的,注解原来也有生命周期。

思考:@Override、@SuppressWarnings和@Deprecated这三个注解的属性值分别是什么?
分别是:SOURCE,SOURCE,RUTIME
@Target元注解:

     @Target注解有两个属性,ElementType.METHOD,ElementType.TYPE,分别表示所修饰的注解类是定义在方法上的,是定义在类型上的(Type是Interface,Enum,Class,@Interface等类型的父类),@Target注解属性的返回值是ElementType[],所以在定义两个属性时要加上{},如@Target({ElementType.METHOD.ElementType.TYPE});

注解的高级属性:

 ⑴数组类型属性

 int [] arrayAttr() default{1,2,30}  @MyAnnotation(arrayAttr={2,3,4})
  如果数组属性中只有一个元素,这时候属性值部分可以省略大括号
 ⑵枚举类型的属性

 EnumTest.TrafficLamp lamp(); @MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN)
注解类型的属性:
MetaAnnotation AnnotationAttr() default@MetaAnnotation("xxxx");@MyAnnotation(annotationAttr=@MetaAnnotation("yyy"))
 可以认为上面这个@MyAnnotation是MyAnnotation类的一个实例对象,同样的道理,可以认为上面这个@MetaAnnotation是MetaAnnotation类的一个实例对象

调用代码如下:

MetaAnnotation ma = myAnnotation.annotationAttr();System.out.println(ma.value());
注解的详细语法可以通过看java语言规范了解,即看java的language specification
注解返回值有八种基本类型 int,byte,char,short,long,float,double,boolean
还有Enum枚举,Annotation注解,以上这些类型的数组。

【总结】从注解的高级属性中可以看出,java提供注解可以说是灵活多变,功能强大,它的使用类型包括java体系中的大部分类型结构,操作范围非常的广阔,而且还可以支持嵌套使用,就是注解有注解,这种灵活运用,更加强大注解的可扩展性,和更加补足了java面向对象的一些局限。


---------------------- Android培训、java培训、期待与您交流! ----------------------详细请查看:www.itheima.com

0 0
原创粉丝点击