kagxin / blog

个人博客:技术、随笔、生活
https://github.com/kagxin/blog/issues
7 stars 0 forks source link

java注解使用 #45

Open kagxin opened 4 years ago

kagxin commented 4 years ago

定义

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

注解和注释的区别

注释是描述程序的,给人看的。注解是说明程序的给计算机(编译器,反射,javadoc)看的

作用分类:

内置注解

典型的注解

@Target({ElementType.TYPE})   //元注解,作用类的注解
@Retention(RetentionPolicy.RUNTIME)  //元注解,保留到运行时
@interface Conf {        //注解的签名
    String className() default "";  //注解属性
    String methodName() default "";
}

元注解

例子1:解析注解中的属性值

image

anno.java

package annoDemo1;

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)  //保留到运行时
@interface Conf {        //注解的签名
    String className() default "";  //注解属性
    String methodName() default "";
}

main.java

package annoDemo1;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/*
执行注解的className对应的类的methodName方法
* */
@Conf(className = "annoDemo1.Persion", methodName = "show")
public class Main {
    public static void main(String[] args) throws Exception {
        Class cls = Main.class;

        Conf conf = (Conf) cls.getAnnotation(Conf.class); // 获取注解

        String className = conf.className();  // 通过注解的属性获取 className, methodName
        String methodName = conf.methodName();
        System.out.println(String.format("%s, %s", className, methodName));

        Class aClass = Class.forName(className);  // 获取Class对象

        Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class);  // 获取注解className属性值对应的类

        Persion xiaoming = (Persion) declaredConstructor.newInstance("xiaoming", 12); //生成对象用于调用方法

        Method declaredMethods = aClass.getDeclaredMethod(methodName); // 获取注解methodName属性值对应的方法
        declaredMethods.invoke(xiaoming);  // 执行方法
    }
}

例子二:简单的测试例子

image

Check.java

package test;

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 {
}

Test.java

package test;

import test.Calc;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) {

        Calc c = new Calc();
        Class cls = c.getClass();  // 获取Calc的Class的对象
        Method[] declaredMethods = cls.getDeclaredMethods();  // 获取所有方法
        int number = 0;
        for (Method declaredMethod : declaredMethods) {
            if (declaredMethod.isAnnotationPresent(Check.class)) {  // 判断是否被Check注解
                try {
                    declaredMethod.invoke(c);    // 执行被Check注解的方法
                } catch (Exception e) {
                    number++;
                    System.out.println(e.getCause().getMessage());
                }
            }
            System.out.println("=========");
        }

        System.out.println(String.format("测试结束:共%s个错误", number));

    }
}
kagxin commented 4 years ago

例子一的完整代码:

anno.java

package annoDemo1;

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)  //保留到运行时
@interface Conf {        //注解的签名
    String className() default "";  //注解属性
    String methodName() default "";
}

Persion.java

package annoDemo1;

public class Persion {
    private String name;
    private int age;

    public Persion(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

    @Override
    public String toString() {
        return "Persion{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Student.java

package annoDemo1;

public class Student extends Persion {
    private int score;

    public Student(String name, int age) {
        super(name, age);
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public void show()
    {
        System.out.println("i am student");
    }

    @Override
    public String toString() {
        return "Student{" +
                "score=" + score +
                '}';
    }
}

Main.java

package annoDemo1;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/*
执行注解的className对应的类的methodName方法
* */
@Conf(className = "annoDemo1.Persion", methodName = "show")
public class Main {
    public static void main(String[] args) throws Exception {
        Class cls = Main.class;

        Conf conf = (Conf) cls.getAnnotation(Conf.class); // 获取注解

        String className = conf.className();  // 通过注解的属性获取 className, methodName
        String methodName = conf.methodName();
        System.out.println(String.format("%s, %s", className, methodName));

        Class aClass = Class.forName(className);  // 获取Class对象

        Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class);  // 获取注解className属性值对应的类

        Persion xiaoming = (Persion) declaredConstructor.newInstance("xiaoming", 12); //生成对象用于调用方法

        Method declaredMethods = aClass.getDeclaredMethod(methodName); // 获取注解methodName属性值对应的方法
        declaredMethods.invoke(xiaoming);  // 执行方法
    }
}
kagxin commented 4 years ago

例二的完整代码

Check.java

package test;

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 {
}

Calc.java

package test;

public class Calc {

    @Check
    public static void add_t() {
        System.out.println(1 + 2);
    }

    @Check
    public static void div_t() {
        System.out.println(1 / 0);
    }

    public static void test() {
        System.out.println("hello");
    }

}

Test.java

package test;
import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) {

        Calc c = new Calc();
        Class cls = c.getClass();  // 获取Calc的Class的对象
        Method[] declaredMethods = cls.getDeclaredMethods();  // 获取所有方法
        int number = 0;
        for (Method declaredMethod : declaredMethods) {
            if (declaredMethod.isAnnotationPresent(Check.class)) {  // 判断是否被Check注解
                try {
                    declaredMethod.invoke(c);    // 执行被Check注解的方法
                } catch (Exception e) {
                    number++;
                    System.out.println(e.getCause().getMessage());
                }
            }
            System.out.println("=========");
        }

        System.out.println(String.format("测试结束:共%s个错误", number));

    }
}