1.什么是注解:
注释: 给程序员看的.
注解: 给JVM看的 , 可以加在包、类、字段、方法、局部变量、方法参数等前面 ,
用来对这些元素说明 , 注释.
注: 一个同名的注解只能使用一次.
2.注解的作用:
- 编写文档: 通过代码里标识的注解生成文档. [ 例: 生成doc文档 ]
- 代码分析: 对代码进行分析. [ 例: 注解的反射 ]
- 编译检查: 让编译器能够实现基本的编译检查. [ 例: Override ]
3.自定义注解:
定义格式:
元注解
public @interface 注解名称{
格式1: 修饰符 数据类型 属性名( );
格式2: 修饰符 数据类型 属性名( ) default 默认值 ;
}
注解的属性:
1.作用: 使用注解时可以传递参数 , 让注解功能更强大.
2.属性使用的数据类型: 四类八种 , String类型 , Class 类型 , 枚举 , 注解类型.
3.特殊属性Value : 当只有一个属性 && 名称是value , 可以直接给属性值.
使用格式:
没有属性: @注解名称
有 属 性 : @注解名称(属性名 = 属性值 , 属性名 = 属性值 … )
value属性: @注解名称(属性值) ;
自定义注解案例:
/*
定义一个注解:Book
- 包含属性:String name() 书名
- 包含属性:double price() 价格,默认值为 100
- 包含属性:String[] authors() 多位作者
*/
public @interface Book {
// 书名
public abstract String name();
// - 包含属性:double price() 价格,默认值为 100
public abstract double price() default 100;
// - 包含属性:String[] authors() 多位作者
public abstract String[] authors();
}
// 定义方法使用
public class TestBook {
// 有默认值的可以不传属性值 , 也可以传 .
@Book(name = "西游记" , authors = "孙悟空" ,price = 88.88)
public void showBook(){
}
}
4.注解之元注解: 用于修饰自定义的注解.
元注解之@Target: 作用: 指明用在哪个位置.
可选参数值: ElementType(枚举类型.)
type: 用在类 , 接口上 .
field: 用在成员变量上 .
method: 用在方法上 .
parameter: 用在参数上 .
constructor: 用在构造方法上.
local_variable: 用在局部变量上.
元注解之@Retention: 作用: 定义该注解的生命周期(有效范围)
可选参数值: RetentionPolicy:
source: 只存在于java源代码中 .
class: 存在于java源代码中 , 编译以后的字节码文件中
runtime: 存在于java源代码中 , 编译后的字节码文件中 , 运行时内存中 . (可通过反射获取注解)
注解解析: 通过java技术获取注解数据的过程.
看程序(就是获取注解的属性值)
isAnnotationPresent( ): 判断(类上,方法上…)是否有指定的注解
参数传递: 要判断注解的class文件对象
getAnnotation(): 获取(类上 ,方法上…)的注解.
参数传递: 要获取的注解的class文件对象.
综合案例:
/*
反射和注解的综合练习题
模拟注解@Test
自定义一个注解@MyTest,并添加元注解(运行中有效,只能用在方法上)
定义一个使用@MyTest类,定义多个方法,部分方法使用@MyTest注解
获取测试类中所有的方法,判断方法上是否有@MyTest注解
有:让方法执行 invoke(obj)
没有:就不执行方法
*/
// 自定义一个注解@MyTest,并添加元注解(运行中有效,只能用在方法上)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
}
// 定义一个类 , 定义多个方法 , 部分方法使用MyTest注解 .
public class TestMyTest {
@MyTest
public void method01(){
System.out.println("method01");
}
public void method02(){
System.out.println("method02");
}
public void method03(){
System.out.println("method03");
}
@MyTest
public void method04(){
System.out.println("method04");
}
}
// 获取测试类中所有的方法,判断方法上是否有@MyTest注解
public class Demo01Annotation {
public static void main(String[] args) throws Exception {
// 创建class文件对象 .
Class<?> clazz = Class.forName("demo07_annotation_$.TestMyTest");
// 获取实例化对象.
Object o = clazz.newInstance();
// 获取测试类中所有的方法 .
Method[] methods = clazz.getMethods();
for (Method method : methods) {
// 判断方法上是否有@MyTest注解
boolean b = method.isAnnotationPresent(MyTest.class);
if(b){
// 有:让方法执行 invoke(obj)
Object o1 = method.invoke(o);
System.out.println(o1);
}
}
}
}