注解,自定义注解和元注解

1.注解

1.1.注解概述、作用

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

  • 注解:说明程序的。给计算机看的
  • 注释:用文字描述程序的。给程序员看的

对Java中类、方法、成员变量做标记,然后进行特殊处理,至于到底做何种处理由业务需求来定。
例如:JUnit框架中,标记了注解@Test的方法就可以被当成测试方法执行,而没有标记的就不能当成测试方法执行

作用分类:

        ①编写文档:通过代码里标识的注解生成文档【生成文档doc文档】

        ②代码分析:通过代码里标识的注解对代码进行分析【使用反射】

        ③编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】

1.2.内置注解

Java中有三种内置注解,这些注解用来为编译器提供指令,它们是:

@Deprecated

​ 这个元素是用来标记过时的元素,编译器在编译阶段遇到这个注解时会发出提醒警告,告诉开发者正在调用一个过时的元素比如过时的方法、过时的类、过时的成员变量

​ 可以用来标记类,方法,属性;

@Override

​ 用来修饰对父类进行重写的方法。如果一个并非重写父类的方法使用这个注解,编译器将提示错误。

​ 实际上在子类中重写父类或接口的方法,@Overide并不是必须的。但是还是建议使用这个注解,在某些情况下,假设你修改了父类的方法的名字,那么之前重写的子类方法将不再属于重写,如果没有@Overide,你将不会察觉到这个子类的方法。有了这个注解修饰,编译器则会提示你这些信息

@SuppressWarnings

​ 用来抑制编译器生成警告信息

​ 可以修饰的元素为类,方法,方法参数,属性,局部变量

​ 当我们一个方法调用了弃用的方法或者进行不安全的类型转换,编译器会生成警告。我们可以为这个方法增加@SuppressWarnings注解,来抑制编译器生成警告。

​ 注意:使用@SuppressWarnings注解,采用就近原则,比如一个方法出现警告,我们尽量使用@SuppressWarnings注解这个方法,而不是注解方法所在的类。虽然两个都能抑制编译器生成警告,但是范围越小越好,因为范围大了,不利于我们发现该类下其他方法的警告信息

//告诉编译器忽略 unchecked 警告信息,如使用List,ArrayList等未进行参数化产生的警告信息。
@SuppressWarnings(“unchecked”)

//如果编译器出现这样的警告信息:The serializable class WmailCalendar does not declare a     //static final serialVersionUID field of type long,使用这个注释将警告信息去掉。
@SuppressWarnings(“serial”)

//如果使用了使用@Deprecated注释的方法,编译器将出现警告信息。使用这个注释将警告信息去掉。
@SuppressWarnings(“deprecation”)

//rawtypes是说传参时也要传递带泛型的参数 
@SuppressWarnings(“rawtypes”) 

//抑制所有类型的警告:
@SuppressWarnings(“all”)

2.元注解

元注解是指用于注解其他注解的注解。在Java中,元注解是一种特殊的注解,用于对其他注解进行修饰和控制。元注解可以用于定义自定义注解的行为、作用范围、生命周期等属性。

本质:注解本质上就是一个接口,该接口默认继承Annotation接口

            * public interface MyAnno extends java.lang.annotation.Annotation {}

元注解有两个:

  •  @Target: 约束自定义注解只能在哪些地方使用,
  •  @Retention:申明注解的生命周期

@Target中可使用的值定义在ElementType枚举类中,常用值如下:

  •  TYPE,类,接口,枚举
  •  FIELD, 成员变量
  • METHOD, 成员方法
  • PARAMETER, 方法参数
  • CONSTRUCTOR, 构造器
  • LOCAL_VARIABLE, 局部变量
  • ANNOTATION_TYPE:注解类型。
  • PACKAGE:包。

@Retention中可使用的值定义在RetentionPolicy枚举类中,常用值如下:

  • SOURCE: 注解只作用在源码阶段,生成的字节码文件中不存在
  •  CLASS:  注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值.
  •  RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段(开发常用)

@Documented:指定注解是否包含在Java文档中。

@Inherited:指定注解是否可以被继承。如果一个注解被@Inherited修饰,那么它将被子类继承。

@Repeatable:指定注解是否可重复应用于同一目标元素。该元注解在Java 8中引入

元注解的作用是为其他注解提供更多的控制和限制。通过使用元注解,开发人员可以定义自己的注解,并指定它们的作用范围、生命周期和其他属性,从而实现更加灵活和可定制的注解功能。

3.自定义注解

自定义注解就是自己做一个注解来使用

  • value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写!!
  • 但是如果有多个属性,  且多个属性没有默认值,那么value名称是不能省略的。

4.注解解析

注解的操作中经常需要进行解析,注解的解析就是判断是否存在注解,存在注解就解析出内容

要获取类方法和字段的注解信息,必须通过Java的反射技术来获取 Annotation对象

与注解解析相关的接口:

  • Annotation: 注解的顶级接口,注解都是Annotation类型的对象
  • AnnotatedElement:该接口定义了与注解解析相关的解析方法

解析注解的技巧:
注解在哪个成分上,我们就先拿哪个成分对象。

  •  比如注解作用成员方法,则要获得该成员方法对应的Method对象,再来拿上面的注解
  •  比如注解作用在类上,则要该类的Class对象,再来拿上面的注解
  •  比如注解作用在成员变量上,则要获得该成员变量对应的Field对象,再来拿上面的注解

5.案例

模拟Junit框架:定义若干个方法,只要加了MyTest注解,就可以在启动时被触发执行

public class Calculator {
    //加法
    @Check
    public void add(){
        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...");
    }
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}
public class TestCheck {
    /**
     * 简单的测试框架
     *
     * 当主方法执行后,会自动自行被检测的所有方法(加了Check注解的方法),判断方法是否有异常,记录到文件中
     */
    public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, IOException {
        //Class cls = Class.forName("annotation.Calculator");
        Calculator c = new Calculator();
        Class<? extends Calculator> cls = c.getClass();
        //获取所有方法
        int number=0;//出现异常的次数
        BufferedWriter br=new BufferedWriter(new FileWriter("bug.txt"));
       Method[] methods = cls.getMethods();
        for (Method m :
                methods) {
            //判断方法上是否有check注释
            if(m.isAnnotationPresent(Check.class)){
                try {
                    m.invoke(c);
                } catch (Exception e) {
                    //捕获异常
                    //记录到文件
number++;
br.write(m.getName()+"方法出异常了");
br.newLine();
br.write("异常名称"+e.getCause().getClass().getSimpleName());
br.newLine();
br.write("异常原因"+e.getCause().getMessage());
                }
            }
        }
        br.write("本次一共出现"+number+"次异常");
        br.flush();
        br.close();
    }
}

  • 25
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值