注解

来源:互联网 发布:java经典代码 编辑:程序博客网 时间:2024/06/05 20:39
如果说注释是给人看的提示信息,则注解是给程序看的提示信息

1.java中提供了很多自带的注解,其中常见的有:
@Override: 限定重写父类方法, 该注解只能用于方法
@Deprecated: 用于表示某个程序元素(类, 方法等)已过时
@SuppressWarnings: 抑制编译器警告. 

常用来替代配置文件

2.自定义注解:
通过 @interface 关键字可以自定义一个注解,自定义一个注解的过程和定义一个接口的过程类似
在注解类中也可以为注解声明一个或多个属性,声明注解属性的过程就像在为一个接口定义方法一样
String name();
String name2() default "xxx";//也可以使用default 关键字为属性设定默认值
String value();//value属性是一个特殊的属性,如果整个注解中只有一个属性,并且这个属性的名字叫做value,则在使用这个注解时,属性的名字可以省略,直接给value的值就可以了
注解的属性可以是如下类型:
String、基本数据类型、枚举、Class 、其它注解类型、以上数据类型相应一维数组

在定义注解的过程中还可以用java中提供的元注解修饰我们自己定义的注解,所谓的元注解指的是sun提供用来描述注解的基本特性的一些注解
(1)!!@Retention:只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 可以保留的域 ,@Override注解属于这种类型;
RetentionPolicy.SOURCE: 表明被修饰的注解是源码级别的注解,只在源码.java文件中存在,在编译器编译的过程中,这个注解被丢弃掉,向这种注解通常是给编译器使用的注解

RetentionPolicy.CLASS: 表明被修饰的注解是字节码级别的注解,这个注解在.java源码和.class字节码文件中存在.在.class文件被加载到内存中时,这个注解被丢弃.除了可以给编译器使用还可以在虚拟机加载类的过程中使用.


RetentionPolicy.RUNTIME:表明被被修的注解是运行阶段的注解,这个注解信息在.java源码.class字节码文件以及程序运行阶段都存在.这样的注解在运行阶段也存在,通常用来通过反射获取,使程序根据注解进行不同的操作.


(2)!!@Target:
指定注解用于修饰类的哪个成员. @Target 包含了一个名为 value,类型为ElementType的成员变量。
ElementType.TYPE, 申明该注解用于类上;
ElementType.METHOD, 用于方法上;
ElementType.FIELD  用于类的属性上;

(3)@Documented: 
用于指定被该元 Annotation 修饰的 Annotation 类将被 javadoc 工具提取成文档.

(4)@Inherited: 
被它修饰的 Annotation 将具有继承性.如果某个类使用了被 @Inherited 修饰的 Annotation, 则其子类将自动具有该注解

4.反射注解:
检查类/方法/类变量/构造方法是否有具体的注解,获取注解,根据注解来执行不同的操作
AnnotatedElement定义了如下方法,而Class/Method/Field/Constructor都实现了这个接口,所以通过这些对象都可以调用如下方法在类/方法/成员变量/构造器上获取或判断是否包含指定的注解
(1)<T extends Annotation>T  getAnnotation(Class<T> annotationClass) 
 如果存在该元素的指定类型的注解,则返回这些注解,否则返回 null。 
 获取了该注解对象以后,就可以获取属性值;
 
(2)Annotation[] getAnnotations() 
 返回此元素上存在的所有注解。 
 
(3)Annotation[] getDeclaredAnnotations() 
 返回直接存在于此元素上的所有注解。
 
(4)boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) 
 如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。 

示例代码:

package com.oterman.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import java.lang.reflect.Field;import java.lang.reflect.Method;/** * 申明一个注解; * @author 大蘑菇 * */@Retention(RetentionPolicy.RUNTIME)//指定该注解保留到运行时;@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})//表明该注解可以用在类上,方法上,属性上;@interface MyAnnotation{public String attribute();//定义属性;//public String value();//比较特殊的属性,如果只有它时,在使用时可以直接赋值;}/** * 演示注解的使用; * @author 大蘑菇 * *///给类加注解;@MyAnnotation(attribute="in class!")class Person{//给属性加注解;@MyAnnotation(attribute="in field!")public String name=null;//给方法加注解;@MyAnnotation(attribute="in method!")public void eat(){}}/** * 测试注解的使用; * @author 大蘑菇 * */public class AnnotationDemo {public static void main(String[] args) throws Exception, NoSuchMethodException {Class clazz=Person.class;//获取类上的注解对象;MyAnnotation an1=(MyAnnotation) clazz.getAnnotation(MyAnnotation.class);//获取属性值;System.out.println(an1.attribute());//in class!//判断方法上是否有某个注解;Method method=clazz.getMethod("eat");boolean b=method.isAnnotationPresent(MyAnnotation.class);System.out.println(b);//true//获取方法注解的属性值;MyAnnotation an2=method.getAnnotation(MyAnnotation.class);System.out.println(an2.attribute());//in method!//获取类属性上的注解的属性值;Field field=clazz.getField("name");MyAnnotation an3=field.getAnnotation(MyAnnotation.class);System.out.println(an3.attribute());//in field!}}


0 0
原创粉丝点击