注解复习
1、什么是注解?
语法:@注解名称
注解的作用:替代xml配置文件!
servlet3.0中,就可以不再使用web.xml文件,而是所有配置都使用注解!
注解是 由框架读取使用的!
2、注解的使用
* 定义注解类: 框架的工作
* 使用注解: 我们的工作
* 读取注解(反射): 框架的工作
3、定义注解类:
class A{}
interface A{}
enum A{}
@interface A{}//天下所有的注解都是Annotation的子类
4、使用注解
注解的作用目标:
package cn.itcast.demo2; @MyAnno1 public class Demo2 { @MyAnno1 private String name; @MyAnno1 public Demo2(){ } @MyAnno1 public void fun1(){ } public void fun2(@MyAnno1 String name){ @MyAnno1 String username="hello"; } } /** * 定义注解 * @author Administrator * */ @interface MyAnno1{ }
*类
*方法
*构造器
*参数
*局部变量
*包
5、注解的属性
*定义属性
>格式:类型 属性名();
*使用注解时给属性赋值
>@Mynoo1(age = 100, name = "zhangSan")
*注解属性的默认值:在定义注解时可以给注解指定默认值
>int age() default 100;在使用注解时,可以不给带有默认值的属性赋值
*名为value的属性的特权
>当使用注解时,如果只给名为value的属性赋值时,可以省略value=部分。例如'@Myanno1(value="hello")'可以省略为'@Myanno1("hello")'
package cn.itcast.demo3; @Mynoo1(age = 100, name = "zhangSan") @Mynoo2(name="liSi") @Mynoo3(100) public class Demo3 { } @interface Mynoo1{ int age(); String name(); } @interface Mynoo2{ int age() default 100; String name(); } @interface Mynoo3{ int value(); String name() default "王"; }
*注解属性的类型
>8种基本类型
>String类型
>Enum
>Class
>注解类型
>以上类型的一维数组类型
*数组只能用这种方式赋值,{}.当给数组类型的属性赋值时,若数组元素的个数为1时,可以省略大括号
package cn.itcast.demo4; @MyAnno1( a=100, b="hello", c=MyEnum1.A, d=String.class, e=@MyAnno2(aa=200,bb="hehe"), f={"",""} //数组只能用这种方式赋值,{}.当给数组类型的属性赋值时,若数组元素的个数为1时,可以省略大括号 ) public class Demo4 { } @interface MyAnno1{ int a(); String b(); MyEnum1 c(); Class d(); MyAnno2 e(); String[] f(); } @interface MyAnno2{ int aa(); String bb(); } enum MyEnum1{ A,B,C }
6、注解的作用目标限定以及保存策略限定
让一个注解,它的作用目标只能在类上,不能再方法上,这就叫作用目标的限定
6.1、在定义注解时,给注解加上一个名为target的注解
@Target(value={ElementType.TYPE,ElementType.METHOD})
package cn.itcast.demo5; import java.lang.annotation.ElementType; import java.lang.annotation.Target; @MyAnno1 public class Demo5 { @MyAnno1 public void fun1(){ } } @Target(value={ElementType.TYPE,ElementType.METHOD}) @interface MyAnno1{ }
6.2、保留策略
*源代码文件(SOURCE):注解只能在源代码中存在,当编译时就被忽略了
*字节码文件(CLASS):注解在源代码中存在,然后编译时会把注解信息放到了Class文件中,但JVM在加载类时会忽略注解
*JVM中(RUNTIME):注解在源代码,字节码中存在,并且在JVM记载类时,会把JVM记载到内存中,它是唯一可以反射的注解
package cn.itcast.demo6; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; public class Demo6 { } @Retention(RetentionPolicy.RUNTIME) @interface MyAnno1{ }
限定注解的保留策略
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno1{
}
7、读取注解(反射):
反射注解
1、要求
*注解的保留策略必须是RUNTIME
2、反射注解需要从作用目标上返回
*类上的注解,需要使用Class来获取
*方法上的注解,需要使用Method来获取
*构造器上的注解,需要使用Constructor来获取
*成员上的,需要使用Field来获取
Class
Method、Constructor、Field:父类:AccessibleObject
他们都有一个方法:
*getAnnotation(Class):得到目标上指定注解
*getAnnotations():得到目标上的注解的数组
package cn.itcast.demo2; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; import org.junit.Test; public class Demo2 { @Test public void fun1(){ /* * 1、得到作用目标 */ Class<A> c=A.class; /* * 2、获取指定类型的注解 */ MyAnno1 myAnno1=c.getAnnotation(MyAnno1.class); System.out.println(myAnno1.name()+"--"+myAnno1.age()+"--"+myAnno1.sex()); } @Test public void fun2() throws SecurityException, NoSuchMethodException{ /* * 1、得到作用目标 */ Class<A> c=A.class; Method method=c.getMethod("fun1", null); /* * 2、获取指定类型的注解 */ MyAnno1 myAnno1=method.getAnnotation(MyAnno1.class); System.out.println(myAnno1.name()+"--"+myAnno1.age()+"--"+myAnno1.sex()); } } @MyAnno1(name="A类",age=1,sex="男") class A{ @MyAnno1(name="fun1方法",age=2,sex="女") public void fun1(){ } } @Retention(RetentionPolicy.RUNTIME) @interface MyAnno1{ String name(); int age(); String sex(); }