java注解-初识

Posted --believe

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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();
    


总结

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

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

以上是关于java注解-初识的主要内容,如果未能解决你的问题,请参考以下文章

java注解-初识

java-初识注解Annotation

Spring MVC注解版本--初识--12

Retrofit初识

初识MyBatis

初识MyBatis