注解详解
1. 什么是注解
语法:@注解名称
注解的作用:替代xml配置文件!servlet3.0中,就可以不再使用web.xml文件,而是所有配置都使用注解!
2. 注解的使用
定义注解类:框架的工作
使用注解:我们的工作
读取注解(反射):框架的工作
3. 定义注解类
@interface A{}//天下所有的注解都是Annotation的子类!
4. 使用注解
注解的作用目标:类,属性,方法,构造器,参数,局部变量,包。
@MyAnno1 //类 public class Demo1 { @MyAnno1 //属性 private String name; @MyAnno1 //构造器 public Demo1() {} @MyAnno1 //方法 public void fun1() {} public void fun2(@MyAnno1/*参数*/ String name) { @MyAnno1 //局部变量 String username = "hello"; } }
5. 注解的属性
定义属性:
@interface MyAnno1 { int age(); String name(); }
使用注解时给属性赋值:@MyAnno1(age=100, name="zhangSan")
注解属性的默认值:在定义注解时,可以给注解指定默认值!int age() default 100;(在使用注解时,可以不给带有默认值的属性赋值!)
名为value的属性的特权:当使用注解时,如果只给名为value的属性赋值时,可以省略“value=”,例如: @MyAnno1(value="hello"),可以书写成 @MyAnno1("hello")
注解属性的类型:8种基本类型,String,Enum,Class,注解类型,以上类型的一维数组类型。
@MyAnno1( a=100, b="hello", c=MyEnum1.A, d=String.class, e=@MyAnno2(value=200,name="abc"), f=100, s={"aaa","bbb"} ) @MyAnno3(100) @interface MyAnno1 { int a(); String b() default "world"; MyEnum1 c(); Class d(); MyAnno2 e(); int[] f(); String[] s(); } @interface MyAnno2 { int value(); String name() default "wangWu"; } @interface MyAnno3 { int value(); } enum MyEnum1 {A, B, C}
6. 注解的作用目标限定以及保存策略限定
6.1 比如让一个注解,它的作用目标只能在类上,不能在方法上,这就叫作用目标的限定!
在定义注解时,给注解添加注解,这个注解是@Target
@Target(value={ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) @interface MyAnno1 {}
6.2 保留策略
源代码文件(SOURCE):注解只在源代码中存在,当编译时就被忽略了
字节码文件(CLASS):注解在源代码中存在,然后编译时会把注解信息放到了class文件,但JVM在加载类时,会忽略注解!
JVM中(RUNTIME):注解在源代码、字节码文件中存在,并且在JVM加载类时,会把注解加载到JVM内存中(它是唯一可反射注解!)
限定注解的保留策略
@Retention(RetentionPolicy.RUNTIME) @interface MyAnno1 {}
反射注解
1. 要求
注解的保留策略必须是RUNTIME
2. 反射注解需要从作用目标上返回
类上的注解,需要使用Class来获取
方法上的注解,需要Method来获取
构造器上的注解,需要Construcator来获取
成员上的,需要使用Field来获取
3. 途径
Method、Constructor、Field三者有一个共同的父类:AccessibleObject,它有两个方法:
Annotation getAnnotation(Class):返回目标上指定类型的注解!
Annotation[] getAnnotations():返回目标上所有注解!
DEMO:
1 import java.lang.annotation.Retention; 2 import java.lang.annotation.RetentionPolicy; 3 import java.lang.reflect.Method; 4 import org.junit.Test; 5 public class Demo { 6 //类上的注解,输出:A类, 1, 男 7 @Test 8 public void fun1() { 9 //1. 得到作用目标 10 Class<A> c = A.class; 11 //2. 获取指定类型的注解 12 MyAnno1 myAnno1 = c.getAnnotation(MyAnno1.class); 13 System.out.println(myAnno1.name() + ", " + myAnno1.age() + ", " + myAnno1.sex()); 14 } 15 //方法上的注解,输出:fun1方法, 2, 女 16 @Test 17 public void fun2() throws SecurityException, NoSuchMethodException { 18 //1. 得到作用目标 19 Class<A> c = A.class; 20 Method method = c.getMethod("fun1"); 21 //2. 获取指定类型的注解 22 MyAnno1 myAnno1 = method.getAnnotation(MyAnno1.class); 23 System.out.println(myAnno1.name() + ", "+ myAnno1.age() + ", " + myAnno1.sex()); 24 } 25 } 26 @MyAnno1(name="A类", age=1, sex="男") 27 class A { 28 @MyAnno1(name="fun1方法", age=2, sex="女") 29 public void fun1() {} 30 } 31 @Retention(RetentionPolicy.RUNTIME) 32 @interface MyAnno1 { 33 String name(); 34 int age(); 35 String sex(); 36 }