java注解-初识

注解

所谓注解,跟注释类似,用来对代码中的类、方法、属性进行说明。

作用

  1. 编写文档:通过代码里面标识的注解来生成文档javadoc命令

  2. 代码分析:可以通过反射机制,得知该类、方法、属性是否有注解。比如可以通过反射,调用getAnnotation函数获取该注解然后进行解析注解中的属性。

  3. 编译检查:通过注解能够让编译器自动进行编译检查,比如@overide可以检查是否是重载函数

    可以暂时理解为一个可以存放数据(注解的属性)的“特殊对象”。他的作用主要体现在可以解析他的属性值。看完《自定义注解》就明白了。

元注解

元注解就是标识注解的注解。也就是系统中定义好的注解,方便我们自定义注解的时候对该自定义注解进行描述。

这里只介绍两种最常用的元注解

@Target

这个元注解表示被描述的注解@Anno的适用范围,也就是说@Anno可以作用于类(TYPE)还是属性(FIELD),又或是方法(METHOD)

@Retention

Retention中文维持,表示被描述的注解的保持时间。我们一般设置为RUNTIME,表示时间是从字节码到JVM读取的时间段都能保持。

自定义注解

package cn.itcast.example.example01;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)//被修饰的注解作用范围
@Retention(RetentionPolicy.RUNTIME)//被修饰的注解保持时间,RUNTIME表示从字节码到jVM读取阶段
public @interface MyAno {
    //属性列表,本质是方法
    String className();
    String methodName();
}

定义注解的格式

  1. 通过@interface表示是一个注解(本质上是一个接口)
  2. 注解内部是属性列表,跟定义成员方法一样,返回值+函数名。
  3. 注解上面是元注解,用来限定该注解的特性,比如作用范围、保持时间等。

解析注解

解析注解就是读取注解的属性。具体步骤

  • 创建字节码对象
  • 字节码对象调用getAnnotation获取

案例1-通过注解获取类名和方法,并执行类中的方法

步骤

  1. 获取字节码对象
  2. 字节码对象调用getAnnotation获取注解对象,然后获取注解对象属性值类名和方法名
  3. 利用反射执行类中方法

代码

MyAno.java

package cn.itcast.example.example01;

        import java.lang.annotation.ElementType;
        import java.lang.annotation.Retention;
        import java.lang.annotation.RetentionPolicy;
        import java.lang.annotation.Target;

@Target(ElementType.TYPE)//被修饰的注解作用范围
@Retention(RetentionPolicy.RUNTIME)//被修饰的注解保持时间,RUNTIME表示从字节码到jVM读取阶段
public @interface MyAno {
    //属性列表,本质是方法
    String className();
    String methodName();
}

Main.java

package cn.itcast.example.example01;



@MyAno(className = "cn.itcast.example.domain.Cat",methodName ="shout" )
public class Main {
    public static void main(String[] args) throws Exception {
        Class<Main> cls = Main.class;//通过字节码获取注解对象
        MyAno ano = cls.getAnnotation(MyAno.class);//获取注解对象
        String cn = ano.className();
        String mn = ano.methodName();
        Class<?> cls1 = Class.forName(cn);
        Object o = cls1.getConstructor().newInstance();
        cls1.getMethod(mn).invoke(o);

    }
}

Cat.java

package cn.itcast.example.domain;

public class Cat {
    private String name;

    public Cat() {
    }

    public Cat(String name) {

        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public void shout(){
        System.out.println("喵喵喵");
    }
}

Dog.java

package cn.itcast.example.domain;

public class Dog {
    private String name;

    public Dog(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Dog() {
    }
    public void shout(){
        System.out.println("哇哦哇哦");
    }
}


案例2-通过注解实现测试框架,测试Calculator中的各个方法

步骤

  1. 自定义一个方法注解
  2. 在需要测试的方法上加上注解
  3. 在测试类中利用反射机制获取Calculator字节码对象,获取该对象的所有方法对象。
  4. 方法对象调用getAnnotation获取注解,根据注解有无执行该方法对象。(主要利用了反射机制)

代码

Calculator.java

package cn.itcast.example.example02;

public class Calculator {
    //加法
    @Check
    public void add(){
        String str = null;
        str.toString();
        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.java

package cn.itcast.example.example02;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

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

TestCheck.java

package cn.itcast.example.example02;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestCheck {
    public static void main(String[] args) throws Exception{
        Calculator calculator = new Calculator();
        Class cls = calculator.getClass();
        Method[] declaredMethods = cls.getDeclaredMethods();
//        FileWriter fw = new FileWriter("bug1.txt");

        BufferedWriter fw = new BufferedWriter(new FileWriter("bug.txt"));
        int sum=0,erorNum=0;
        for (Method declaredMethod : declaredMethods) {
//            System.out.println(declaredMethod);
            Check annotation = declaredMethod.getAnnotation(Check.class);
           //如果有注解
            if(null!=annotation){
                sum++;
                try{
                    declaredMethod.invoke(calculator);
                }catch (Exception e){
                    fw.write(declaredMethod.getName()+"出异常了");
                    fw.newLine();
                    fw.write(e.getCause().toString());
                    fw.newLine();
                    fw.write("---------------");
                    fw.newLine();
                    erorNum++;
                }

            }

        }
        fw.write("一共测试了"+sum+"个函数");
        fw.newLine();
        fw.write("出错了"+erorNum+"个函数");
        fw.newLine();
        fw.flush();
        fw.close();
    }
}

总结

实际开发过程中我们一般是使用注解,一般不会去自定义注解,但是我们需要知道注解本质就是一个接口,在接口中定义一些方法列表(在注解中称为属性列表)。

可以利用反射机制获取注解,从而解析注解得到里面的属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值