如果说注释是给人看的提示信息,则注解是给程序看的提示信息
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文件中存在,在编译器编译的过程中,这个注解被丢弃掉,向这种注解通常是给编译器使用的注解
(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。
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文件被加载到内存中时,这个注解被丢弃.除了可以给编译器使用还可以在虚拟机加载类的过程中使用.
(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!
}
}