注解是JDK1.5的新特性。
注解相当一种标记,是类的组成部分,可以给类携带一些额外的信息。
标记(注解)可以加在包,类,字段,方法,方法参数以及局部变量上。
注解是给编译器或JVM看的,编译器或JVM可以根据注解来完成对应的功能。
引用数据类型:类,接口,数组,枚举,注解
注解的作用就是给程序带入参数。
以下几个常用操作中都使用到了注解:
生成帮助文档:@author和@version
@author:用来标识作者姓名。
@version:用于标识对象的版本号,适用范围:文件、类、方法。
使用@author和@version注解就是告诉Javadoc工具在生成帮助文档时把作者姓名和版本号也标记在文档中。如下图:
IDEA中生成文档的方式:
编译检查:@Override
@Override:用来修饰方法声明。
**框架的配置( 框架 = 代码 + 配置 ) **
public @interface 注解名{
}
如:定义一个名为Student的注解
public @interface Student {
}
注解本质上就是一个接口。所有注解都会继承一个接口:Annotation
属性的格式
属性定义示例
// 姓名
String name();
// 年龄
int age() default 18;
// 爱好
String[] hobby();
属性适用的数据类型
* 八种数据数据类型(int,short,long,double,byte,char,boolean,float)
* String,Class,注解类型,枚举类
* 以上类型的数组形式
public @interface Book {
String value();
double price() default 100;
String[] authros();
}
public class AnnotationDemo01 {
@Book(value = "JavaEE开发详解",authros = {"黑马程序员","传智学院"})
public void show(){
}
}
如果注解中只有一个属性且名字叫value,则在使用该注解时可以直接给该属性赋值,而不需要给出属性名。
如果注解中除了value属性之外还有其他属性且只要有一个属性没有默认值,则在给属性赋值时value属性名也不能省略了。
因此,如果注解中只有一个属性时,一般都会将该属性名命名为value
public class Demo01 {
@C("ccc")//如果有其他的属性,并且都含有default,都使用默认值的情况下,只给value赋值的情况下也可以省略value=
@B(value = "bb", age = 18)//如果出了value还有其他的属性而且没有default数据,不能省略value=
@A("aa") //如果只有value属性,赋值时,可以省略 value=
public void test1() {
}
}
@interface A {
String value();
}
@interface B {
String value();
int age();
}
@interface C {
String value();
int age() default 18;
}
? Java官方提供的注解 用来定义注解的注解 任何官方提供的非元注解的定义都使用到了元注解。
元注解的作用:用来限定其他注解的生命周期,限定可以使用的地方。
作用:用来标识注解使用的位置,如果没有使用该注解标识,则自定义的注解可以使用在任意位置。
可使用的值定义在ElementType枚举类中,常用值如下
TYPE,类,接口
FIELD, 成员变量
METHOD, 成员方法
PARAMETER, 方法参数
CONSTRUCTOR, 构造方法
LOCAL_VARIABLE, 局部变量
作用:用来标识注解的生命周期(有效范围)
可使用的值定义在RetentionPolicy枚举类中,常用值如下
SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在
CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,【默认值】
RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段
【代码示例】
示例中为JDK定义的@override注解
什么是注解解析? 使用Java技术获得注解上数据的过程则称为注解解析。
Annotation: 注解类的父类型,该类是所有注解的父接口。
AnnotatedElement:该接口定义了与注解解析相关的方法
1. T getAnnotation(Class<T> annotationClass)
根据注解类型获得对应注解对象
2. Annotation[] getAnnotations()
获得当前对象上使用的所有注解,返回注解数组,包含父类继承的
3. Annotation[] getDeclaredAnnotations()
得当前对象上使用的所有注解,返回注解数组,只包含本类的
4. boolean isAnnotationPresent(Class<Annotation> annotationClass)
判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false
Field,Method,Constructor,Class等类都是实现了AnnotatedElement接口
注解作用在哪个成员上就会得该成员对应的对象来获得注解
比如注解作用成员方法,则要获得该成员方法对应的Method对象
比如注解作用在类上,则要该类的Class对象
比如注解作用在成员变量上,则要获得该成员变量对应的Field对象。
自定义注解
//自定义注解
@Target({ElementType.METHOD,ElementType.TYPE}) //作用在方法和类上
@Retention(RetentionPolicy.RUNTIME) //在运行时候有效
@interface Bookshelf{
//属性
String name();
double price() default 9.9;
String[] authors();
}
注册到Book实体类
@Bookshelf(name = "红楼梦",price = 99.9,authors = {"曹雪芹","AAA"})
public class Book {
@Bookshelf(name = "西游记",authors = {"吴承恩","BBB"})
public void show(){}
}
测试类解析
package com.homework_test.test02;
import java.lang.reflect.Method;
import java.util.Arrays;
public class Test {
public static void main(String[] args)throws Exception {
//创建Book类的字节码对象(获取类上的注解)
Class<Book> bookClass = Book.class;
//判断该class对象是否使用了该 注解
if(bookClass.isAnnotationPresent(Bookshelf.class)){
//获得该注解类型的对象
Bookshelf bookshelf = bookClass.getAnnotation(Bookshelf.class);
String name = bookshelf.name();
System.out.println("name = " + name);//name = 红楼梦
String[] authors = bookshelf.authors();
System.out.println("authors = " + Arrays.toString(authors));//authors = [曹雪芹, AAA]
double price = bookshelf.price();
System.out.println("price = " + price);//price = 9.9
}
System.out.println("************************************");
//解析方法上的注解
//1.通过class对象获取指定方法对象
Method showMethod = bookClass.getMethod("show");
//2.开始解析注解
if(showMethod.isAnnotationPresent(Bookshelf.class)){
//获取注解对象
Bookshelf bookshelf = showMethod.getAnnotation(Bookshelf.class);
String name = bookshelf.name();
System.out.println("name = " + name);//name = 西游记
double price = bookshelf.price();
System.out.println("price = " + price);//price = 99.9
String[] authors = bookshelf.authors();
System.out.println("authors = " + Arrays.toString(authors));//authors = [吴承恩, BBB]
}
}
}
原文:https://www.cnblogs.com/liqiliang1437/p/13155692.html