Java 注解

Java 注解

一、注解

Java 注解(Annotation)/java 标注;用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。Java 注解是从 Java5 开始添加到 Java 的。

日常开发中新建Java类,我们使用class、interface比较多,而注解和它们一样,也是一种类的类型,他是用的修饰符为 @interface

在这里插入图片描述

1、注解基础知识

注解的定义

**注释:**文字描述介绍程序,提供给程序员查看的帮助信息。

**注解:**也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释

概念描述:

  1. 1.5之后新特性
  2. 解释说明程序。
  3. 注解使用:@注解

作用分类:

  1. **编写文档:**通过代码里标识的元数据/注解生成文档【生成文档doc文档/java API
  2. **代码分析:**通过代码里标识的元数据/注解对代码进行分析【使用反射
  3. **编译检查:**通过代码里标识的元数据/注解让编译器能够实现基本的编译检查【Override

2、内置注解

2.1、@Override

检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误

@Override
public String toString() {
	return "AnnoTest{}";
}

2.2、@Deprecated

标记过时方法。如果使用该方法,会报编译警告。如:Date

@Deprecated
public  void test1(){
	// 过时方法
    Date d = new Date();
	d.setYear(123);
}

2.3、@SuppressWarnings

指示编译器去忽略注解中声明的警告。一般参数为:all 即就是 @SuppressWarnings("all")

@SuppressWarnings("all")
public  void demo() {
	Date d = new Date();
	d.setYear(123);
}
@SuppressWarnings("all")
public class AnnoTest 

3、自定义注解

3.1、定义格式:

@元注解
public @interface 注解名称{
    属性;
}

3.2、注解的本质:

public interface MyAnno extends java.lang.annotation.Annotation {}
// 本质上就是一个接口默认继承Annotation

在这里插入图片描述

3.3、注解属性

接口中定义的成员抽象方法。要求:

  1. 属性的返回值类型有要求:1,基本类型 2,String 3,枚举 4,注解 5,以上类型的数组
  2. 定义了属性在使用时需要给属性赋值:1,使用default 有初始值可以不赋值。2,如果只有一个属性需要赋值,并且为value,value可以省略。3,数组赋值用{},只有一个值{}可以省略
// 定义一周七天的枚举类型
public enum WeekDayEnum { Mon, Tue, Wed, Thu, Fri, Sat, Sun, }
public static void main(String[] args) {
    WeekDayEnum day = null;
    switch (day) {
        case Mon:
            break;
        case Mon2:
            break;
    }
}

3.4、元注解

描述注解的注解

@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})// MyAnno3注解只能作用于类上
@Retention(RetentionPolicy.RUNTIME)// 保留到class字节码中,被JVM读取。
@Documented// 生成api文档
@Inherited// 会被继承
public @interface MyAnno3 {
}@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

分类:

  • @Target - 标记这个注解应该是哪种 Java 成员。

    *ElementType:*TYPE 类上 METHOD 方法上 FIELD 子成员变量

  • @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。

    RetentionPolicyRUNTIME 会保留到class字节码中,被JVM读取。 CLASS 也会保留到class字节码中,但不被JVM读取。SOURCE

  • @Documented - 标记这些注解是否包含在用户文档api中。

  • @Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)。

4、程序中使用(解析)注解

获取注解中定义的属性值

/**
 * 描述执行的类名和方法名
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Pro {
    String className();

    String methodName();
}
/**
 * public class ProImple implements Pro{
 *     String className(){
 *         return demo2.Demo1;
 *     }
 *     String methodName(){
 *         return test;
 *     }
 * }
 */

反射注解

@Pro(className = "demo2.Demo1",methodName = "test")
public class ReflectTest {
    public static void main(String[] args) throws Exception{
        // 解析注解
        // 1.获取字节码对象
        Class<ReflectTest> rtc = ReflectTest.class;
        // 2.获取注解
        Pro annotation = rtc.getAnnotation(Pro.class);// 在内存中生成注解接口的子类实现对象
        // 3.调用方法
        String s = annotation.className();
        String s1 = annotation.methodName();
        System.out.println(s);
        System.out.println(s1);
        // 反射
        Class<?> cls = Class.forName(s);// 加载class文件
        Object obj = cls.newInstance();// 构造对象
        Method method = cls.getMethod(s1);// 找到指定方法
        method.invoke(obj);// 运行方法
    }
}

Demo1

public class Demo1 {
    public void test(){
        System.out.println("Demo1...test...");
    }
}

流程:

  1. 获取注解定义位置的对象。
  2. 获取指定注解。getAnnotation()
  3. 调用注解的抽象方法,获取属性值。

5、反射获取注解

自定义注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Check {}

测试对象

public class Calculator {
    // +
    @Check
    public void add() {
        String name = null;
        System.out.println(name.equals(123));
        System.out.println("1 + 0 =" + (1 + 0));
    }
    // -
    @Check
    public void sub() {
        System.out.println("1 - 0 =" + (1 - 0));
    }
    // *
    @Check
    public void mul() {
        System.out.println("1 × 0 =" + (1 * 0));
    }
    // /
    @Check
    public void div() {
        System.out.println("1 ÷ 0 =" + (1 / 0));
    }

    public void show(){
        System.out.println("没有 BUG");
    }
}

测试用例

/**
 * 测试框架
 * 主方法执行主动监测带 @Check 的方法,有异常记录
 */
public class TestCheck {
    public static void main(String[] args) throws Exception{
        // 1.获取计算器对象
        Calculator c = new Calculator();
        // 2.获取字节码文件对象
        Class cls = c.getClass();
        // 3.获取执行方法
        Method[] methods = cls.getMethods();
        int count = 0; // 异常记录
        BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));

        // 4.判断有 @Check 并执行
        for (Method method : methods) {
            if (method.isAnnotationPresent(Check.class)) {
                try {
                    method.invoke(c);
                } catch (Exception e) {
                    // 5.捕获异常
                    // e.printStackTrace();
                    // 6.记录
                    count++;
                    bw.write(method.getName()+"方法异常了!");
                    bw.newLine();// 换行
                    bw.write("异常名称:"+e.getCause().getClass().getSimpleName());// 异常原因对象
                    bw.newLine();// 换行
                    bw.write("异常原因"+e.getCause().getMessage());
                    bw.newLine();// 换行
                    bw.write("------------------------------------------");
                    bw.newLine();// 换行
                }
            }
        }
        bw.write("本次测试一共出现异常"+count+"次");

        bw.flush();
        bw.close();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值