注解是JDK1.5的新特性。
注解相当于一种标记,是类的组成部分,可以给类携带⼀一些额外的信息。
标记(注解)可以加在包,类,字段,方法,方法参数以及局部变量上。
注解是给编译器或JVM看的,编译器或JVM可以根据注解来完成对应的功能。
注解的作用
注解的作用就是给程序带入参数。
以下几个常用操作中都使用到了注解:
1. 编译检查:@Override
@Override:用来修饰方法声明
用来告诉编译器该方法是重写父类中的方法,如果父类不存在该方法,则编译失败。
2. 框架的配置(框架=代码+配置)
常见注解
1. @author:用来标识作者名,eclipse开发中具默认的是系统用户名。
2. @version:用于标识对象的版本号,适用范围:文件、类、方法。
3. @Override :用来修饰方法声明,告诉编译器该方法是重写父类中的方法,如果父类不存在该方法,则编译失败。
自定义注解
1. 注解定义格式
@interface 注解名{
数据类型 属性名();
数据类型 属性名() default 默认值;
}
2. 注解属性适用类型
* 八种基本数据类型:byte,short,int,long,char,float,double,boolean
* 引用数据类型:String,Class,注解,枚举类型
* 以上数据类型的数组形式
掌握注解的使用格式和注意事项
1. 注解的使用格式
无属性注解使用格式:@注解名
有属性注解使用格式:@注解名(属性名=属性值,...)
public @interface Student {
String name(); // 姓名
int age() default 18; // 年龄
String gender() default "男"; // 性别
}
// 该注解就有了三个属性:name,age,gender
2. 注解使用注意事项
* 如果属性没有默认值,则使用注解时必须给该属性赋值
* 如果属性有默认值,则使用注解时可以不用给该属性赋值
3. 注解使用演示
3.1 定义一个注解:Book
- 包含属性:String value() 书名
- 包含属性:double price() 价格,默认值为 100
- 包含属性:String[] authors() 多位作者
public @interface Book {
String value();// 书名
double price() default 100;// 价格
String[] authors();// 多位作者
}
3.2 定义类在成员方法上使用Book注解
@Book(value = "三国演义",authors = {"罗贯中"},price = 99)
public class Demo10 {
@Book(value = "三国演义",authors = {"罗贯中"},price = 99)
private String name;
@Book(value = "西游记",authors = {"吴承恩","白求恩"},price = 1000)
public void buy(){
}
}
常用元注解的作用
1. 元注解概述
官方定义的注解
用来定义注解的注解
任何官方的非元注解的定义都使用到了元注解
2. 常用元注解
@Target
作用:用来标识注解的使用位置,比如成员变量,成员方法,构造方法上
value属性常用值定义在枚举类ElementType中,常用枚举值如下:
TYPE, 注解可以使用在类和接口上
FIELD, 注解可以使用在成员变量上
METHOD, 注解可以使用在成员方法上
CONSTRUCTOR, 注解可以使用在构造方法上
@Retention
作用:用来标识注解的有效范围(生命周期)
value属性值定义在枚举类RetentionPolicy中,常用值如下:
SOURCE:源代码阶段 ==> 注解仅仅存在于源文件中,编译产生的class文件中就不存在了
ClASS:字节码文件阶段 ==> 注解存在于源文件,字节码文件中,运行时注解就不存在了,默认是字节码阶段
RUNTIME:运行时阶段 ==> 注解存在于整个运行的运行过程中。
@Document
说明该注解将被包含在javadoc中
@Inherited
说明子类可以继承父类中的该注解
注解的解析
1. 什么是注解解析
* 通过Java代码获得注解信息(属性值)的过程则称为注解解析
2. 注解解析相关接口和类
* Annotation:类 所有注解的父类
* AnnotatedElement:接口 定义了与获取注解信息的相关方法,方法如下:
T getAnnotation(Class<T> annotationClass)
根据注解类型获得注解对象
Annotation[] getAnnotations()
获得当前对象上使用的所有注解,包括父类
Annotation[] getDeclaredAnnotations()
获得当前对象上使用的所有注解,不包括父类的
boolean isAnnotationPresent(Class<Annotation> annotationClass)
* 判断当前对象上是否使用了指定类型的注解,使用了返回true,否则false 3. 注解解析的原理
* 注解作用在哪个成员上就获得该成员对应的对象来解析注解
* 比如:注解作用在类上,那么需要获得类对应的Class对象
* 比如:注解作用在成员方法上,那么需要获得该成员方法对应Method对象
* 比如:注解作用在构造方法上,那么需要获得该构造方法对应Constructor对象
* 比如:注解作用在成员变量上,那么需要获得该成员变量对应Field对象
须知:Class/Method/Field/Constructor都实现了AnnotatedElement接口
4. 注解解析示例演示
4.1 定义注解Book,要求如下:
- 包含属性:String value() 书名
- 包含属性:double price() 价格,默认值为 100
- 包含属性:String[] authors() 多位作者
- 限制注解使用的位置:类和成员方法上
- 指定注解的有效范围:RUNTIME
4.2 定义BookStore类,在类和成员方法上使用Book注解
4.3 定义TestAnnotation测试类获取Book注解上的数据
// 获得类上使用的book注解信息
@Test
public void test02(){
// 获得Class对象
Class c = BookStore.class;
// 判断Class对象上是否使用了Book注解
if(c.isAnnotationPresent(Book.class)){
// 获得Book注解
Book book = (Book) c.getAnnotation(Book.class);
// 获得注解属性信息
System.out.println(book.value());
System.out.println(book.price());
System.out.println(Arrays.toString(book.authors()));
}
}
// 获得BookStore类成员方法buy上使用的book注解信息
@Test
public void test01() throws Exception{
// 获得Class对象
Class c = BookStore.class;
// 根据方法名获得Method对象
Method method = c.getMethod("buy");
// 判断book是否为null
if(method.isAnnotationPresent(Book.class)){
// 获得Book注解
Book book = method.getAnnotation(Book.class); // null
// 获得注解属性信息
System.out.println(book.value());
System.out.println(book.price());
System.out.println(Arrays.toString(book.authors()));
}
}