《Java-SE-第三十八章》之注解

前言

在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!”

博客主页:KC老衲爱尼姑的博客主页

博主的github,平常所写代码皆在于此

共勉:talk is cheap, show me the code

作者是爪哇岛的新手,水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!



注解

概述

Java注解是Java5引入的一种注释解释,又称之为标注。Java中的类,构造器,方法,成员变量,参数等都可以被注解进行标注。我们可以将注解理解为标签,标签可以上的内容可以自由的定义,它是对人和事物属性的评价。这就如商品上的价格标签,图书馆中的书本编码标签,B站上游戏分区标签等。

注解的作用

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

特殊属性

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

自定义注解格式

public @interface 注解名称 {

​ public 属性类型 属性名() default 默认值;

}

代码示例

public @interface MyDemo {
    
    
    String value();
    String name();
    boolean flag() default true;
    String [] str();
}

元注解

元注解就是注解的注解,注解的标签。

常用的元注解

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

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

  • TYPE,类
  • 接口 FIELD,
  • 成员变量METHOD,
  • 成员方法PARAMETER,
  • 方法参数CONSTRUCTOR,
  • 构造器LOCAL_VARIABLE
  • 局部变量

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

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

注解的解析

示例代码

@Target({
    
    ElementType.TYPE,ElementType.METHOD})// 当前被修饰的注解只能用在类上,方法上。
@Retention(RetentionPolicy.RUNTIME)// 控制下面的注解一直保留到运行时
public @interface  MyTest {
    
    
}

MyTest的使用

@MyTest
public class AnnotationTest {
    
    
//    @MyTest
//    private String name;

    @MyTest
    @MyDemo(value = "Annotation",name="张三",str={
    
    "java","C++"})
    public static void test() {
    
    
        System.out.println("Hello World");
    }

    public static void main(String[] args) {
    
    
        test();
    }
}

如果把@MyTest修饰在成员变量上就会报错—>java: 注释类型不适用于该类型的声明

注解的解析

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

与注解解析相关的接口

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

相关API如下

方法 说明
Annotation[] getDeclaredAnnotations() 获得当前对象上使用的所有注解,返回注解数组。
T getDeclaredAnnotation(Class annotationClass) 根据注解类型获得对应注解对象
boolean isAnnotationPresent(Class annotationClass) 判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false

所有的类成分Class, Method , Field , Constructor,都实现了AnnotatedElement接口他们都拥有解析注解的能力。

注解解析案例

首先定义一个MyTest2注解

@Target({
    
    ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest2 {
    
    
    String value();
    String name();
    boolean flag() default true;
    String [] str();
}

在Demo类和方法上使用

@MyTest2(value = "大小姐",name ="林黛玉",str={
    
    "java","C++"})
public class Demo {
    
    
    @MyTest2(value = "小小姐",name ="薛宝钗",str={
    
    "java","Python"})
    public void test() {
    
    

    }

}

解析类上的注解

public class AnnotationTest2 {
    
    
    public static void main(String[] args) {
    
    
        //1.得到class对象
        Class<Demo> demoClass = Demo.class;
        //2.判断类上是否包含注解
        if (demoClass.isAnnotationPresent(MyTest2.class)) {
    
    
            MyTest2 myTest2 = demoClass.getDeclaredAnnotation(MyTest2.class);
            System.out.println(myTest2.value());
            System.out.println(myTest2.name());
            System.out.println(myTest2.flag());
            System.out.println(Arrays.toString(myTest2.str()));
        }
    }
}

运行结果:
在这里插入图片描述

解析方法上的注解

public class AnnotationTest3 {
    
    

    public static void main(String[] args) throws NoSuchMethodException {
    
    
        //1.得到class对象
        Class<Demo> demoClass = Demo.class;
        Method test = demoClass.getDeclaredMethod("test");
        //2.判断方法对象上是否包含注解
        if (test.isAnnotationPresent(MyTest2.class)) {
    
    
            MyTest2 myTest2 = test.getDeclaredAnnotation(MyTest2.class);
            System.out.println(myTest2.value());
            System.out.println(myTest2.name());
            System.out.println(myTest2.flag());
            System.out.println(Arrays.toString(myTest2.str()));
        }
    }
}

运行结果:

在这里插入图片描述

模拟Junit中的@Test

我们定义若干个方法,只要加了MyTest注解,就可以在启动时被触发执行

分析

  1. 定义一个自定义注解MyTest,只能注解方法,存活范围是一直都在。
  2. 定义若干个方法。只要有@MyTest注解的方法就能在启动时被触发执行,没有这个注解的方法不能执行。

示例代码

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

public class TestDemo {
    
    
    @MyTest
    public void test1() {
    
    
        System.out.println("test1");
    }
    @MyTest
    public void test2() {
    
    
        System.out.println("test2");
    }
    @MyTest
    public void test3() {
    
    
        System.out.println("test3");
    }
    @MyTest
    public void test4() {
    
    
        System.out.println("test4");
    }

    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
    
    
        TestDemo t = new TestDemo();
        //启动程序
        //1.得到TestDemo对象
        Class<TestDemo> testDemoClass = TestDemo.class;
        //提取类中的方法
        Method[] declaredMethods = testDemoClass.getDeclaredMethods();
        //触发方法
        for (Method method : declaredMethods) {
    
    
            if (method.isAnnotationPresent(MyTest.class)) {
    
    
                method.invoke(t);
            }
        }
    }
}

运行结果:

在这里插入图片描述

各位看官如果觉得文章写得不错,点赞评论关注走一波!谢谢啦!。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_60308100/article/details/132306204