注解
JDK内置预定义的注解:
* JDK中预定义的注解
* @Override :检测该方法是否为父类中方法的重写
* @Deprecated: 该注解标注的内容已过时
* @SupperessWarnings: 压制警告
1 package cn.ftf.annotation;
2 /*
3 * JDK中预定义的注解
4 * @Override :检测该方法是否为父类中方法的重写
5 * @Deprecated: 该注解标注的内容已过时
6 * @SupperessWarnings: 压制警告
7 */
8 @SuppressWarnings(value = { "all" }) //压制警告,需要传值,一般传all
9 public class Annotation01 {
10 public static void main(String[] args) {
11
12 }
13 @Override //重写toString方法,检查是否为父类中方法的重写
14 public String toString() {
15 // TODO Auto-generated method stub
16 return super.toString();
17 }
18 @Deprecated //标识说明该方法已过时
19 public void shou1() {
20 //有缺陷
21 }
22 public void shou2() {
23 //替代shou1()方法
24 }
25 public void demo() {
26 shou1();
27 }
28
29 }
30
31 class Student{
32
33 }
自定义注解:
* 自定义注解
* 格式
* 元注解
* public @interface 注解名
*
* 本质:
* 注解本质上是一个接口,该接口默认继承Annotation接口
* public interface MyAnno extends java.lang.annotation.Annotation{}
* 属性:
* 接口中定义的抽象方法
* 要求:
* 属性的返回值有要求:基本数据类型,String,枚举,注解,以上类型的数组.定义了属性后,在使用时需要给他们赋值,也可以在注释中在属性后面用default给属性设值,如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接写值即可
* 注解是否被子类继元注解:用于描述注解的注解
* @Target:描述注解可以作用的位置
* @Retention:描述注解被保留的阶段,一般都是保留到runtime阶段
* @Documented: 描述注解是否被抽取到API文档中
* @Inherited:描述注解是否可以被其子类继承
元注解:
1 package cn.ftf.annotation;
2
3 import java.lang.annotation.Documented;
4 import java.lang.annotation.ElementType;
5 import java.lang.annotation.Inherited;
6 import java.lang.annotation.Retention;
7 import java.lang.annotation.RetentionPolicy;
8 import java.lang.annotation.Target;
9
10 /*
11 * 元注解:用于描述注解的注解
12 * @Target:描述注解可以作用的位置
13 * @Retention:描述注解被保留的阶段,一般都是保留到runtime阶段
14 * @Documented: 描述注解是否被抽取到API文档中
15 * @Inherited:描述是否可以继承到所继承的子类中
16 */
17
18 @Target(value= {ElementType.TYPE}) //表示该注解只能作用在类上,可叠加.TYPE类上,.METHOD方法上,.FLELD成员变量上
19 @Retention(RetentionPolicy.RUNTIME) //当前被描述的注解会被保留到class文件中,并被虚拟机(jvm)读取到
20 @Documented //当前注解可以被抽取到API文档中
21 @Inherited //当前注解可以被继承到所继承的子类中
22 public @interface MyAnno03 {
23
24 }
首先定义一个注解:Myanno.java
1 package cn.ftf.annotation;
2
3 public @interface MyAnno {
4 String name() default "张三";
5 int age();
6 Person per(); //枚举
7 MyAnno2 anno2();
8 String[] str();
9 }
一个枚举:Person.java:
1 package cn.ftf.annotation;
2
3 public enum Person {
4 p1,p2;
5 }
注解的声明和属性赋值:
1 package cn.ftf.annotation;
2 /*
3 * 自定义注解
4 * 格式
5 * 元注解
6 * public @interface 注解名
7 *
8 * 本质:
9 * 注解本质上是一个接口,该接口默认继承Annotation接口
10 * public interface MyAnno extends java.lang.annotation.Annotation{}
11 * 属性:
12 * 接口中定义的抽象方法
13 * 要求:
14 * 属性的返回值有要求:基本数据类型,String,枚举,注解,以上类型的数组.定义了属性后,在使用时需要给他们赋值,也可以在注释中在属性后面用default给属性设值,如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接写值即可
15 * 注解是否被子类继元注解:用于描述注解的注解
16 * @Target:描述注解可以作用的位置
17 * @Retention:描述注解被保留的阶段
18 * @Documented: 描述注解是否被抽取到API文档中
19 * @Inherited:描述注解是否可以被其子类继承
20 */
21
22 @MyAnno(age = 20, per = Person.p1, anno2 = @MyAnno2, str = { "123","567" }) //注解声明和各种属性(方法)的赋值
23 public class AnnotationDemo02 {
24
25 }
解析注解:
定义一个注解:Prp.java
1 package cn.ftf.annotation;
2
3 import java.lang.annotation.Documented;
4 import java.lang.annotation.ElementType;
5 import java.lang.annotation.Retention;
6 import java.lang.annotation.RetentionPolicy;
7 import java.lang.annotation.Target;
8
9 /*
10 *描述需要执行的类名和方法名
11 */
12 @Target(ElementType.TYPE) //可以作用于类上
13 @Retention(RetentionPolicy.RUNTIME) //会被保留到class文件中
14 public @interface Pro {
15 String className();
16 String methodName();
17
18 }
对注解解析,拿到注解的属性:
1 package cn.ftf.annotation;
2
3 import java.lang.annotation.Annotation;
4
5 @Pro(className = "cn.ftf.annotation.Demo1", methodName = "show")
6 public class ReflectTest {
7 public static void main(String[] args) {
8 //解析注解
9 //获取该类的字节码文件对象
10 Class<ReflectTest> c=ReflectTest.class;
11 //获取字节码文件的注解对象
12 Pro p=c.getAnnotation(Pro.class); //其实就是在内存中生成生成了一个该注解接口的子类实现对象
13 String className=p.className();
14 String methodName=p.methodName();
15 System.out.println(className+" "+methodName); //拿到注解内容
16 }
17 }
下面应用注解和反射做一个简单的测试框架:

测试一个类(Calculaor类)中的方法是否有错误
1 package cn.ftf.annotationpro;
2 /*
3 * 定义了一个计算机的类
4 */
5 public class Calculator {
6 @Check
7 public void add() {
8 System.out.println("1+0="+(1+0));
9 }
10 @Check
11 public void del() {
12 System.out.println("1-0="+(1-0));
13 }
14 @Check
15 public void mul() {
16 System.out.println("1*0="+(1*0));
17 }
18 @Check
19 public void div() { //显然div方法中由错误(by zero)
20 System.out.println("1/0="+1/0);
21 }
22 public void show() {
23 System.out.println("永无bug...");
24 }
25 }
定义一个接口:Check.java
1 package cn.ftf.annotationpro;
2
3 import java.lang.annotation.ElementType;
4 import java.lang.annotation.Retention;
5 import java.lang.annotation.RetentionPolicy;
6 import java.lang.annotation.Target;
7
8 @Target(ElementType.METHOD)
9 @Retention(RetentionPolicy.RUNTIME)
10 public @interface Check {
11 }
定义测试类TestCheck.java:
1 package cn.ftf.annotationpro;
2
3 import java.io.BufferedWriter;
4 import java.io.FileWriter;
5 import java.io.IOException;
6 import java.lang.reflect.InvocationTargetException;
7 import java.lang.reflect.Method;
8
9 /*
10 * 简单的测试类,当主方法执行,会检测该类下所有的需要检测的方法,并记录到文件中
11 */
12 public class TestCheck {
13 public static void main(String[] args) throws IOException {
14 //获取要检测的类的计算器对象
15 Calculator cal= new Calculator();
16 //获取字节码文件对象
17 Class c=cal.getClass();
18
19 //获取所有的方法
20 Method[] me=c.getMethods();
21 int number =0; //记录出现异常的次数
22 BufferedWriter bw=new BufferedWriter(new FileWriter("D:\\myjavacode\\ftf001\\src\\cn\\ftf\\annotationpro\\bugNote.txt"));
23 //方法上是否由check注解
24 for(Method m:me) {
25 if(m.isAnnotationPresent(Check.class)) {
26 try {
27 m.invoke(cal);
28 } catch (Exception e) {
29 number++;
30 //记录到文件中
31 bw.write(m.getName()+"方法出异常了!");
32 bw.newLine();
33 bw.write("异常名称:"+e.getCause().getClass().getSimpleName());
34 bw.newLine();
35 bw.write("异常原因:");
36 bw.write(e.getCause().getMessage());
37 bw.newLine();
38
39 }
40 }
41 }
42 bw.write("本次一共出现"+number+"次异常!");
43 bw.close();
44 }
45 }
结果:


浙公网安备 33010602011771号