java注解

注解作用

  • 编译检查
  • 文档生成,javadoc
  • 代码分析,使用反射对代码的注释进行分析

jdk预定义注解

@Override注解

  用于重写父类的方法 或者是写接口实现类时用到该注解。

@Deprecated注解

  用于表示该方法是一个过期的方法。

@suppressWarnings注解

  表示该方法在编译时自动忽略警告。
public class Test {
    @Override
    public String toString() {
        return super.toString();
    }

    @Deprecated
    public void test1()
    {
        //弃用
    }

    @SuppressWarnings("all")
    public void test2()
    {
        //压制所有警告
    }
}

自定义注解

本质是一个接口,继承自java。lang。annotation.Annotation

格式

//public interface Yungang extends java.lang.annotation.Annotation {}
public @interface Yungang {

}

属性

接口中的抽象方法
属性的返回值只能是以下取值:

  • 基本类型
  • String
  • 枚举
  • 注解
  • 以上类型的数组

特点:
1.定义了属性后,需要给属性赋值,或者在注解中使用default
2.只有一个属性时,并且属性名称为value,则可以省略名称

元注解

@Target

  描述注解能够作用的位置

ElementType的取值:

  • TYPE:类
  • METHOD: 方法
  • FIELD:成员变量

@Retention

  描述注解被保留的阶段
  • RetentionPolicy.RUNTIME : 当前被描述的注解,会保留到class字节码文件中,并被JVM读取到

@Document

  描述注解是否被抽取到api文档中

@Inherited

  描述注解会被子类继承
@Target(value = {ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Yungang {
    String test1();

    double test2();
}

测试

@Yungang(test1 = "test", test2 = 3.0)
public class Test {
    @Override
    public String toString() {
        return super.toString();
    }

    @Deprecated
    public void test1()
    {
        //弃用
    }

    @SuppressWarnings("all")
    public void test2()
    {
        //压制所有警告
    }

    @Yungang(test1 = "test2", test2 = 1.0)
    public void test3(){

    }
}

解析注解

获取注解中定义的属性值,可用于配置文件

获取注解定义的位置(类、函数、属性 )的对象

获取指定注解,getAnnotation(class)

例子

定义注解类

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassInfo {
    String classname();

    String methodname();
}

使用注解,获取注解值

@ClassInfo(classname = "com.reflect.Person", methodname = "show")
public class TestReflect {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取当前类字节码
        Class<TestReflect> testReflectClass = TestReflect.class;
        //通过字节码获取当前类的注解对象

        // 这里的 annotation 是实现了ClassInfo接口的子类,故可以调用方法获取返回值(返回定义的值)
        ClassInfo annotation = testReflectClass.getAnnotation(ClassInfo.class);

        // 使用反射拿到配置中类和方法
        Class aClass = Class.forName(annotation.classname());
        Constructor constructor = aClass.getConstructor();
        Person person = (Person) constructor.newInstance();
        person.function("xyg");

    }
}

Person类

ublic class Person {
	public Person() {

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

	public void function(String s) {
		System.out.println("function:" + s);
	}
}

自定义测试类

注解类

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

要测试的方法上添加自定义注解

public class Calculator {

    @JunitDemo
    public void test1(){
        System.out.println(1 / 2);
    }

    @JunitDemo
    public void test2(){
        System.out.println("true = " + true);
    }

    @JunitDemo
    public void test3(){
        System.out.println(2 / 0);  // 此方法有异常,使用测试类找出
    }

}

使用注解,找到有异常的方法

        Calculator calculator = new Calculator(); // 获取测试类
        Class aClass = calculator.getClass(); // 获取字节码
        Method[] methods = aClass.getMethods(); // 获取测试类所有方法

        for (Method method: methods
             ) {
            // 遍历所有方法,找到存在JunitDemo注解的方法
            if (method.isAnnotationPresent(JunitDemo.class))
            {
                try {
                    // 执行方法,并捕获异常
                    method.invoke(calculator);
                }catch (Exception e) {
                    // 打印方法名并输出异常类型
                    System.out.println("method: " +method.getName() + " have exception , type is "+ e); 
                }
            }
        }
    }

参考:https://www.bilibili.com/video/BV1Vt411g7RP?p=6

原文地址:https://www.cnblogs.com/xiongyungang/p/12873017.html