1. 注解的使用
* 定义注解类:框架的工作
* 使用注解:我们的工作
* 读取注解(反射):框架的工作,tomcat利用反射,读取servlet 中的注解的
3 Java中的注解
Java中的觉注解:
- @Overrid:作用在方法上的注解。检查方法是不是父类继承的方法,当方法不是重写父类的方法时会报错;
- @Deprecated:作用在方法上。标记该方法为作废方法(已过时);
- @SuppressWarnings:作用在方法上,压制警告
@interface A{}//天下所有的注解都是Annotation的子类
4 使用注解目标
注解可以作用在:类(接口或枚举)、属性、方法、构造器、包(可以放,但是一般不用特殊方法可以放)、参数、局部变量
package cn.itcast.annocation;
@MyAnn public class MyClass { @MyAnn private int a; @MyAnn public MyClass() {} @MyAnn public void fun1() {} @MyAnn public void fun2(@MyAnn String s) { @MyAnn int n = 10; } } |
5 注解的属性
4. 使用注解
注解的作用目标:
* 类
* 方法
* 构造器
* 参数
* 局部变量
* 包
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(aa=200, bb="world"),
f=100// 当给数组类型的属性赋值时,若数组元素的个数为1时,可以省略大括号{100,200} {100}
)
public class Demo3 {
}
@interface MyAnno1 {
int a();
String b();
MyEnum1 c();
Class d();
MyAnno2 e();
int[] f();
}
@interface MyAnno2 {
int aa();
String bb();
}
enum MyEnum1 {
A, B, C
}
}
定义注解时也可以给出属性
public @interface MyAnn { String value(); int value1(); } |
其中value就是属性!你可能会说,它是一个方法!没错,它是一个方法,但我们非要称之为属性,因为把它当做属性更加好理解。
当为注解指定属性后,那么在使用注解时就必须要给属性赋值了:
@MyAnn(value1=100,value="hello") public class MyClass { } |
注解的属性还可以有默认值,在使用注解时就可以不给带有默认值的属性赋值了。但没有给出默认值的属性还是要赋值的。
public @interface MyAnn { String value() default "hello world"; int value1(); } |
@MyAnn(value1=100) 使用注解时,没有给出value属性,因为它有默认值,可以不赋值。但value1没有默认值就必须赋值。当然也可以给带有默认值的属性赋值。 public class MyClass { } |
在使用注解时,如果只给名为value的属性赋值,那么可以不给出属性的名称直接给出值。
public @interface MyAnn { String value() default "hello world"; int value1() default 100; } |
@MyAnn() 因为所有属性都有默认值,所以没问题 public class MyClass { } |
@MyAnn(value="hello") public class MyClass { } |
@MyAnn(value1=200) public class MyClass { } |
@MyAnn(value="hello",value1=200) public class MyClass { } |
@MyAnn("hello annocation") 因为value属性是String类型的,所以出错! public class MyClass { } |
@MyAnn(300) 因为value属性是String类型的,所以出错! public class MyClass { } |
@MyAnn("hello",value1=200) 出错!因为不是给一个属性赋值,那么这时就不能再省略属性的名字。 public class MyClass { } |
6. 注解的作用目标限定以及保存策略限定
- 注解的属性后面要有一对圆括号,而且圆括号内不能给出东西。就像是无参的方法一样;
- 注解的属性类型只能是:基本类型、String、Enum、Class、注解类型、以上类型的一维数组类型;
- 注解的属性可以有默认值,例如:int a() default 100;
- 数组的属性默认值:int[] arr() default {1,2,3},这里不能使用new int[]{1,2,3}
- 使用注解时,在给数组属性赋值时的格式:@MyAnn(arr={1,2,3});
6 注解的作用目标
在定义注解时可以限制注解的作用目录!例如让注解只能作用在类和方法上。
这需要使用元注解:@Target。该注解有一个属性value,类型为ElementType[],它是枚举类型。
public @interface Target { ElementType[] value(); } |
public enum ElementType { TYPE,FIELD,METHOD,PARAMETED,CONSTRUCTOR,LOCAL_VARIABLE,ANNOCATION_TYPE,PACKAGE } |
在定义注解时,可以使用@Target注解来限制注解的作用目标:
@Target({ElementType.TYPE, ElementType.METHOD}) public @interface MyAnn { } |
这样MyAnn就只能作用在类和方法上的!其中ElementType.TYPE表示类和接口。
@MyAnn() public class MyClass { 出错!因为MyAnn被限制只能作用在类和方法上,不能作用在属性上。 @MyAnn() private int a;
@MyAnn() public void fun() {} } |
7 注解的保留策略
注解的保留策略是指,注解是只保留在源代码上,还是保留到class文件上,再或者是类在运行时,可以被类加载器加载到内存中。
如果希望注解被反射,那么注解就要保留到运行时,而不是源代码或类文件上。
指定注解的保留策略需要使用元注解@Retention,它有一个value属性,类型为RetentionPolicy类型,RetentionPolicy是枚举类型:
public @interface Retention { RetentionPolicy value(); } |
public enum RetentionPolicy { SOURCE, CLASS, RUNTIME } |
下面代码是指定注解保留到运行时
@Retention(RetentionPolicy.RUNTIME) 注解保留到运行时 @Target({ElementType.TYPE, ElementType.METHOD}) public @interface MyAnn { String value() default "hello"; int value1() default 100; } |
8 通过反射读取注解
读取注解需要使用反射来完成
@Retention(RetentionPolicy.RUNTIME) 保留到运行时,如果不设置为保留到运行时,那么就无法反射出来 @Target({ElementType.TYPE, ElementType.METHOD}) public @interface MyAnn { String value() default "hello"; int value1() default 100; } |
@MyAnn(value="hello world", value1=200) public class MyClass { private int a;
@MyAnn("myMethod") public void fun() {} } |
public class Demo1 { public static void main(String[] args) throws Exception { Class clazz = MyClass.class; MyAnn myAnn = (MyAnn) clazz.getAnnotation(MyAnn.class); System.out.println(myAnn.value()); System.out.println(myAnn.value1());
Method method = clazz.getMethod("fun"); MyAnn myAnn1 = method.getAnnotation(MyAnn.class); System.out.println(myAnn1.value()); System.out.println(myAnn1.value1()); } } |