认识注解
- 什么是注解?
注解的语法是@注解名
,多用来替代配置文件配置项。它是由框架解读的(使用反射)。可以把注解对比注释理解,注释是给人看的,注解是给框架看的。
- 注解的使用
- 注解定义:框架的工作
- 注解使用:我们的工作
- 注解解读:框架的工作
- 定义一个注解
所有注解的父接口都是annotation的子接口
// 定义注解
public @interface MyAnno1 {
}
可以使用注解的位置:
/**
* 注解默认可以用在
* 类、构造方法、方法、成员变量、形参、局部变量、包(不常用)上
*/
@MyAnno1
public class Demo1 {
@MyAnno1
private String name;
@MyAnno1
public Demo1() {
}
@MyAnno1
public void fun1(@MyAnno1 String param) {
@MyAnno1
String s = "demo";
}
}
注解属性
- 注解的属性
@MyAnno1(age = 20, name = "张三")
public class Demo2 {
}
// 注解属性的书写方式
@interface MyAnno1 {
int age();
String name();
}
- 注解属性的默认值
// 可以不需要给带有默认值得属性赋值
@MyAnno1(name = "李四")
public class Demo3 {
}
@interface MyAnno1 {
int age() default 20;
String name();
}
- 注解的value属性
注解的value属性具有特殊性,特殊性表现在使用中。
// 当只有value属性时,可以省略value=
@MyAnno1(100)
// 有其他属性时,不能省略
@MyAnno2(value = 100, name = "张三")
@MyAnno3(100)
public class Demo4 {
}
@interface MyAnno1 {
int value();
}
@interface MyAnno2 {
int value();
String name();
}
@interface MyAnno3 {
int value();
String name() default "李四";
}
- 属性的类型
@MyAnno1(
a = 20, b = "hello", c = Demo5.class, d = MyEnum.A,
e = @MyAnno2(age = 30, name = "张三", flag = true), // 当数组元素只有一个时,可以省去大括号
f = {1, 2, 3}
)
public class Demo5 {
}
/**
* 属性的类型可以是8大基本类型、String、Class、Enum、注解类型、以上类型的一纬数组
* 注意包装类型不能使用
*/
@interface MyAnno1 {
int a();
String b();
Class c();
MyEnum d();
MyAnno2 e();
int[] f();
}
enum MyEnum {
A, B, C
}
@interface MyAnno2 {
int age();
String name();
boolean[] flag();
}
注解的目标限定和保留策略
- 注解的目标限定,限定的是注解可以作用的目标
@MyAnno1
public class Demo6 {
// 在方法上使用@MyAnno1将会报错
// @MyAnno1
public void fun1(){
}
}
// @Target是限定注解作用的目标,ElementType枚举表示可作用的多种类型
@Target(ElementType.TYPE)
@interface MyAnno1{
int value() default 10;
}
- 注解的保留策略
- 保留在源码中(SOURCE):编译为Class文件时就不存在了。
- 保留在字节码文件中(CLASS):保留在class文件中,class文件加载到内存中就不存在了。
- 保留在内存中(RUNTIME):保留在运行时环境中,只有这种保留策略可以使用反射解读注解。
@MyAnno1
public class Demo7 {
}
// 保留策略为Runtime
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno1 {
}
反射注解
/**
* 反射注解
*/
public class Demo8 {
public static void main(String[] args) throws NoSuchMethodException {
Class<A> aClass = A.class;
// 类上的注解
MyAnno1 annotation = aClass.getAnnotation(MyAnno1.class);
System.out.println(annotation.age() + "," + annotation.name());
// 获取方法上的注解
Method fun1 = aClass.getMethod("fun1");
MyAnno1 anno1 = fun1.getAnnotation(MyAnno1.class);
System.out.println(anno1.name() + "," + anno1.age());
}
}
@MyAnno1(age = 2, name = "张顺飞")
class A {
@MyAnno1(age = 1, name = "李老八")
public void fun1() {
}
}
@Retention(RetentionPolicy.RUNTIME)// 必须要限定为RUNTIME才能使用反射获取
@interface MyAnno1 {
String name();
int age();
}