注解-Annotation Types学习

2023-11-18

前言:注解是JDK5 之后推出的特性,可修饰包、类、方法、变量等,通过在编译、加载和运行时读取其信息,可执行相应的处理。

基本原理

java注解类型实质上是一个标记,如:

@Autowired
private TestBean testBean;

@Autowired标记了testBean这个域属性,这个标记的意义就是自动注入,告诉spring这个域属性需要注入该类型的对象。

通过反射机制,可以得到相应的注解,并对注解进行定制化处理,如@Deprecated 标记过期,@Override 标记重写函数。
注解本身有无,并不影响程序的编译如@Override,但可能会影响程序的正常运行,如@Autowired,若删掉该注解,则对应域属性没有实例化的bean,产生异常。

注解组成

注解由来
public interface Annotation {

    boolean equals(Object obj);

    int hashCode();

    String toString();

    Class<? extends Annotation> annotationType();
}

注解不是新的东西,也是需要通过java原生语言来定义,Annotation接口声明了注解的源头。在定义注解时,仅需要在定义接口时,在interface 前加 @ 即可定义成功。@interface 实际上继承了 java.lang.annotation.Annotation 表明自己为注解类型。

注:注解本身不能再被继承,且无法通过extends java.lang.annotation.Annotation 方式声明自己的注解类型

以@Override为例,对注解的定义进行讲解。@Override 表明该方法覆盖了其父类或接口的方法。其上又包含了@Target与@Retention两个注解。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
  • @Target注解表明该注解可标注的位置,其内部接受一个ElementType类型的数组,ElementType类型如下:
public enum ElementType {

    /** 标明该注解可以用于类、接口(包括注解类型)或enum声明 */
    TYPE,
    /** 标明该注解可以用于字段(域)声明,包括enum实例 */
    FIELD,

    /** 标明该注解可以用于方法声明 */
    METHOD,

    /** 标明该注解可以用于参数声明 */
    PARAMETER,

    /** 标明注解可以用于构造函数声明 */
    CONSTRUCTOR,

    /** 标明注解可以用于局部变量声明 */
    LOCAL_VARIABLE,

    /** 标明注解可以用于注解声明(应用于另一个注解上)*/
    ANNOTATION_TYPE,

    /** 标明注解可以用于包声明 */
    PACKAGE,

    /**
     * 标明注解可以用于类型参数声明(1.8新加入)
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * 类型使用声明(1.8新加入)
     * @since 1.8
     */
    TYPE_USE
}
  • @Retention表明注解的生命周期,其接受RetentionPolicy枚举值,RetentionPolicy类型如下:
public enum RetentionPolicy {
    /**
     * 信息只保留在源码中,编译时将丢弃
     */
    SOURCE,

    /**
     * 信息只保留在源码和 编译后的class文件中,但加载到JVM时将被丢弃。
     */
    CLASS,

    /**
     * 信息将保留在源码、class文件以及运行时。
     */
    RUNTIME
}

再看这两个注解的定义:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

可见这两个注解自身也被自身标记,并声明了自身的声明周期及作用对象。

@Target和@Retention注解中,包含了value()方法,并含有返回值。该方法表明了注解接受何种类型的属性值。如@Target接受ElementType类型的数组,该属性值将由该注解定义者来决定如何使用。

其中,注解内可定义多个方法,且多种返回类型,但由限制。

  • 对于方法,若有属性值且无默认值,则必须提供该属性的值,如@Target(ElementType.ANNOTATION_TYPE)或定义默认值。
value() default ElementType.ANNOTATION_TYPE

当注解内有唯一的方法,且方法名为value() 则,在使用时,无须通过key=value形式,直接赋值即可,如@Target(ElementType.ANNOTATION_TYPE),否则需要通过@Target(value=ElementType.ANNOTATION_TYPE)赋值。

  • 对于返回值,需要在以下类型范围内,且不能接受null值。
所有基本类型(int,float,boolean,byte,double,char,long,short)

String

Class

enum

Annotation

上述类型的数组

public @interface AnnotationElementDemo {
    //枚举类型
    enum Status {FIXED,NORMAL};

    //声明枚举
    Status status() default Status.FIXED;

    //布尔类型
    boolean showSupport() default false;

    //String类型
    String name()default "";

    //class类型
    Class<?> testCase() default Void.class;

    //注解嵌套
    Override reference();

    //数组类型
    long[] value();
}

注解信息使用
返回值 方法名 说明
<A extends Annotation> getAnnotation(Class<A>annotationClass) 该元素如果存在指定类型的注解,则返回这些注解,否则返回 null。
Annotation[] getAnnotations() 返回此元素上存在的所有注解,包括从父类继承的
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) 如果指定类型的注解存在于此元素上,则返回 true,否则返回 false。
Annotation[] getDeclaredAnnotations() 返回直接存在于此元素上的所有注解,注意,不包括父类的注解,调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响,没有则返回长度为0的数组

简单实例:

package com.zejian.annotationdemo;

import java.lang.annotation.Annotation;
import java.util.Arrays;

/**
 * Created by zejian on 2017/5/20.
 * Blog : http://blog.csdn.net/javazejian [原文地址,请尊重原创]
 */
@DocumentA
class A{ }

//继承了A类
@DocumentB
public class DocumentDemo extends A{

    public static void main(String... args){

        Class<?> clazz = DocumentDemo.class;
        //根据指定注解类型获取该注解
        DocumentA documentA=clazz.getAnnotation(DocumentA.class);
        System.out.println("A:"+documentA);

        //获取该元素上的所有注解,包含从父类继承
        Annotation[] an= clazz.getAnnotations();
        System.out.println("an:"+ Arrays.toString(an));
        //获取该元素上的所有注解,但不包含继承!
        Annotation[] an2=clazz.getDeclaredAnnotations();
        System.out.println("an2:"+ Arrays.toString(an2));

        //判断注解DocumentA是否在该元素上
        boolean b=clazz.isAnnotationPresent(DocumentA.class);
        System.out.println("b:"+b);

        /**
         * 执行结果:
         A:@com.zejian.annotationdemo.DocumentA()
         an:[@com.zejian.annotationdemo.DocumentA(), @com.zejian.annotationdemo.DocumentB()]
         an2:@com.zejian.annotationdemo.DocumentB()
         b:true
         */
    }
}

Demo

@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @ interface PersonalName {
    String filedName() default "";

    String methodName() default "";

    String className() default "";
}


@PersonalName(className = "测试类")
public class TestBean {

    @PersonalName(filedName = "我的名字")
    public String myName= "";

    @PersonalName(filedName = "你的名字")
    public String yourName="";

    @PersonalName(methodName = "打印A")
    public void printA(){
        System.out.println("A");
    }
}

public class JunitTest {

    private Class<?> test = TestBean.class;

    @Test
    public void testPrintFiled(){
        for(Field field:test.getDeclaredFields()){
            //getDeclaredAnnotations
            Annotation[] annotations = field.getDeclaredAnnotations();
            for (Annotation ann:annotations){
                if(ann instanceof PersonalName){
                    System.out.println("类:"+test.getName()+",属性:"+field.getName()+",自定义名:"+((PersonalName) ann).filedName());
                }
            }

            //getDeclaredAnnotation
            Annotation annotationFiled = field.getAnnotation(PersonalName.class);
            if(annotationFiled!=null){
                System.out.println("类:"+test.getName()+",属性:"+field.getName()+",自定义名:"+((PersonalName) annotationFiled).filedName());

            }
        }
    }

    @Test
    public void testMethod(){
        for(Method method:test.getDeclaredMethods()){
            Annotation annotationMethod = method.getAnnotation(PersonalName.class);
            if(annotationMethod!=null){
                System.out.println("类:"+test.getName()+",方法:"+method.getName()+",自定义名:"+((PersonalName) annotationMethod).methodName());
            }
        }
    }

    @Test
    public void testClass(){
        Annotation annotation = test.getAnnotation(PersonalName.class);
        TestBean testBean = null;
        if(annotation!=null){
            System.out.println("类:"+test.getName()+",自定义名:"+((PersonalName) annotation).className());
            try{
                testBean = (TestBean) test.newInstance();
                testBean.printA();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

注解-Annotation Types学习 的相关文章

  • 一键生成微信小程序的制作工具-小程序切片工具

    微信小程序前端开发者工具 小程序切片 是一款根据效果图像画画一样来设计微信小程序 自动生成导出前端页面的快速开发工具 可以很方便 快速地生成小程序的wxml wcss js文件 可以大大提高您的工作效率 减少前端布局的编写工作 功能如下 1
  • Node(4)

    文章目录 express跨域解决 路由传参 静态资源渲染 serve static MVC 1 新建文件夹 routers 路由管理utils工具类 2 新建文件夹 controller 请求处理 3 新建文件夹 model service
  • TensorRT学习(实战-自定义算子)

    YOLOv4进行TensorRT推理的时候会使用Mish激活函数 而使用到的mish激活函数没有在TensorRT进行实现 故需要进行实现对应TensorRT插件 故需要进行Mish激活函数的实现 Mish激活函数定义 def mish f
  • Arduino - 字符判断函数

    Arduino 字符判断函数 字符判断函数 虽然在实际编程中可能很少使用到 但是可以作为知识储备 有必要了解一些 这些函数包含在ctype h当中 Arduino IDE路径 C Program Files x86 Arduino hard
  • Python入门教程完整版,Python所有方向学习体系,学完即可就业

    今天给大家带来了干货 Python入门教程完整版 完整版啊 完整版 言归正传 小编该给大家介绍一下这套教程了 希望每个小伙伴都沉迷学习 无法自拔 本套教程学习时间15天 1 3天内容 为Linux基础命令 4 13天内容 为Python基础
  • 导入 导出 jeesite框架封装

    为什么80 的码农都做不了架构师 gt gt gt JeeSite的Excel导入 导出 支持大数据量 使用annotation最小化配置 介绍 对Apache POI 3 9的简单封装 实现Excel的导出导入功能 使用Annotatio
  • 数据库 --- 约束

    一 什么是约束 常见的约束有那些 约束是在创建表的时候 可以给表的字段添加相应的约束 添加约束的目的是为了保证表中数据的合法性 有效性 完整性 常见的约束有 非空约束 not null 唯一约束 unique 主键约束 primary ke
  • Some Tips in Life

    How to Find Digital Books 1 http so baiduyun me 百度云搜索 2 http www zhaofile com 找文件 3 http www cnepub com 掌上书苑 4 http vdis
  • java定义时钟类clock_Java 编程题,定义一个时钟类(Clock)

    题目 Java 编程题 定义一个时钟类 Clock 要求如下 1 存储时钟的时hour 0 23 分minute 0 59 秒second 0 59 2 创建新对象时默认为0时0分0秒 3 设置时钟为指定的时间 4 使时钟前进1秒钟的功能i
  • jstat 命令

    NAME jstat Monitors Java Virtual Machine JVM statistics This command is experimental and unsupported SYNOPSIS jstat Opti
  • mongoDB数据库----简介

    目录 目录 一 NoSQL 1 关系型数据库遵循ACID规则 2 分布式系统 3 分布式计算的优点 4 分布式计算的缺点 5 什么是NoSQL 6 NoSQL 简史 7 NoSQL的优点 缺点 8 NoSQL 数据库分类 二 MongoDB
  • 你知道ChatGPT有哪些商业价值吗?不知道,那没意思

    这段时间 热度zui大的是什么 答案是 ChatGPT 去年11月底上线 当时仅在AI和科技圈内小火了一把 没想到在今年春节后 火爆出圈 ChatGPT的爆火 对商家和品牌方 还有投资创业者来说 是个机遇 普通人虽然很难参与到这些高科技的投
  • Python 求两个正整数的最大公约数

    辗转相除法 思路 1 将两整数求余 a b x 2 如果x 0 则b为最大公约数 3 如果x 0 则 a b b x 继续从1开始执行 4 也就是说该循环的是否继续的判断条件就是x是否为0 代码如下 def main a int input
  • javascript经典代码推荐

  • 基于Matlab的高精度轨道传播器模拟

    基于Matlab的高精度轨道传播器模拟 传播器模拟是一种常见的工程方法 用于预测和分析卫星 火箭或其他天体在轨道上的运动 在这篇文章中 我们将使用Matlab编写一个高精度轨道传播器模拟器 并提供相应的源代码 轨道传播器模拟器的主要目标是根
  • FRP服务器搭建成功后,配置多个客户端使用

    FRP内网穿透服务器搭建成功后 在服务器后台启动FRP 然后还需要两步 第一 在域名购买的网站 比如阿里云 配置一条所有子域名到服务器IP的规则 第二 配置多个客户端 A电脑的配置信息如下 common server addr 服务器IP
  • 前端八股文系列(四)4 JavaScript

    文章目录 前端八股文系列 四 4 JavaScript JS中的8种数据类型及区别 JS中的数据类型检测方案 1 typeof 2 instanceof 3 Object prototype toString call instanceof
  • LeetCode-1781. 所有子字符串美丽值之和【哈希表,字符串,计数】

    LeetCode 1781 所有子字符串美丽值之和 哈希表 字符串 计数 题目描述 解题思路一 简单暴力 双层循环 重点是分别记录子字符串 i j 的最大最小频率 注意这里当i变的时候 所有字符出现的频率就清理 否则在原来的基础上加就行 解
  • 栈的应用一之括号匹配问题

    括号匹配问题 给一个类似这样的字符串 char a abc 检测三种括号的左右括号是否匹配 分析 先取出一个字符 并判断是不是括号 任意括号 1 不是括号 取下一个字符 2 是括号 1 是左括号 压栈 2 是右括号 和栈顶元素比较 栈空 前
  • 教程:使用C#实现PDF文件和字节数组的相互转换

    字节数组有助于存储或传输数据 同样 PDF文件格式因其功能和兼容性而广受欢迎 可以使用C 语言将PDF文件转换为字节数组 也可以将字节数组转换为PDF文件 这可以帮助更有效地在数据库中存储和归档PDF文件 还可以通过使用字节数组来序列化数据

随机推荐