java注解和自定义注解

news2025/4/15 5:33:47

目录

一、注解的概念

二、注解的类型

2.1、内置注解

2.2、元注解

2.2.1、各个元注解的作用

2.3、自定义注解

2.4、自定义注解实现及测试


一、注解的概念

1、注解的作用
①:注解一般用于对程序的说明,就像注释一样,但是区别是注释是给人看的,但是注解是给程序看的。
②:让编译器进行编译检查的作用,比如下边这个@Override注解是重写的意思,子类重写了父类的方法,但是改动了方法名,所以报错。

2、注解的格式
注解是以“@注解名”在代码当中存在的,还可以添加一些参数值,例如 @SuppressWarnings(value = “unchecked”)

3、注解在哪里使用
可以附加在package、class、method、field等上面,相当于给他们添加了额外的辅助信息。我们可以通过反射的方式对这些注解进行访问。

二、注解的类型

一般常用的注解分为三类:

2.1、内置注解

①:@Override:修辞方法的,表示一个方法重写了父类方法

②:@Deprecated:修辞方法、属性、类,表示不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。通俗来说就是遗弃。

③:@SuppressWarnings:用来抑制编译时的警告信息,括号里的的值包括

  • deprecation:使用了过时的类或方法的警告
  • unchecked:执行了未检查时的转换时的警告,集合就是未指定泛型
  • fall through:当在switch语句使用时发生case穿透
  • path:在类路径、源文件路径等中有不存在路径的警告
  • serial:可序列化类上缺少serialVerisonUID定义时的警告
  • finally:任何finally橘子不能完成时的警告
  • all:以上所有情况的警告。

一个 @SuppressWarnings(“all”),
多个 @SuppressWarnings(value={“all”,“path”})

2.2、元注解

元注解的作用是负责对其他注解进行说明的注解。自定义注解时可以使用元注解。Java 5 定义了 4 个注解,分别是 @Documented、@Target、@Retention 和 @Inherited;Java 8 又增加了 @Repeatable 和 @Native 两个注解。可以在java.lang.annotation包中找到。

2.2.1、各个元注解的作用

1、@Target 指定一个注解的使用范围

即被 @Target 修饰的注解可以用在什么地方

@Target源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
   
    ElementType[] value();
    
}

@Target 注解有一个成员变量(value)用来设置适用目标。以下为注解的枚举常量:

public enum ElementType {
    /** 类、接口(包括注解类型),或者枚举声明 */
    TYPE,

    /** 字段声明(包括枚举常量) */
    FIELD,

    /** 方法声明 */
    METHOD,

    /** 形参声明 */
    PARAMETER,

    /** 构造方法声明 */
    CONSTRUCTOR,

    /** 局部变量声明 */
    LOCAL_VARIABLE,

    /** 注解类型声明 */
    ANNOTATION_TYPE,

    /** 包声明 */
    PACKAGE,

    /**  类型参数声明 */
    TYPE_PARAMETER,

    
    /** 类型的使用 */
    TYPE_USE
}

2、@Retention  描述注解保留的时间范围

即被描述的注解在它所修饰的类中可以被保留到何时

@Retention注解源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
   
    RetentionPolicy value();
    
}

他的value是 java.lang.annotation.RetentionPolicy 枚举类型。

public enum RetentionPolicy {
   
   	//源文件保留
    SOURCE,

  	//编译期保留,默认值
    CLASS,

  	//运行期保留,可通过反射去获取注解信息
    RUNTIME
    
}

        生命周期大小排序为 SOURCE < CLASS < RUNTIME,前者能使用的地方后者一定也能使用。

        如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解,如 @Documented 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码,就用 CLASS 注解,如 @NonNull 注解;如果只是做一些检查性的操作,则可选用 SOURCE 注解,如 @Override 和 @SuppressWarnings 注解。

3、@Documented  描述javadoc

描述在使用javadoc工具为类生成帮助文档时是否要保留其注解信息。

@Documented注解源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

@Documented 是一个标记注解,没有成员变量。用 @Documented 注解修饰的注解类会被 JavaDoc 工具提取成文档。默认情况下,JavaDoc 是不包括注解的,但如果声明注解时指定了 @Documented,就会被 JavaDoc 之类的工具处理,所以注解类型信息就会被包括在生成的帮助文档中。

4、@Inherited 阐述了某个被标注的类型是被继承的

@Inherited 是一个标记注解,用来指定该注解可以被继承。如果某个类使用了被@Inherited修饰的注解,则其子类将自动具有该注解。

举个例子:

注解

@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyInheritedAnnotation {

    public String name() default "liuliu";

}

父类

@MyInheritedAnnotation(name = "parent")
public class Parent {
}

子类

public class Child extends Parent {

    public static void main(String[] args) {
        Class<Child> child = Child.class;
        MyInheritedAnnotation annotation = child.getAnnotation(MyInheritedAnnotation.class);
        System.out.println(annotation.name());
    }

}

输出:
parent

5、@Repeatable注解

@Repeatable 是Java 8 新增@Repeatable注解用于声明标记的注解为可重复类型注解,可以在同一个地方多次使用。Java 8 版本以前,同一个程序元素前最多只能有一个相同类型的注解,如果需要在同一个元素前使用多个相同类型的注解,则必须使用注解“容器”。

@Repeatable 注解源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {
    
    Class<? extends Annotation> value();
    
}

举个例子

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRepeatableAnnotation {

    RepeatableAnnotationTest[] value();

}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(MyRepeatableAnnotation.class)
public @interface RepeatableAnnotationTest {

    String key();

    String value();

}
@RepeatableAnnotationTest(key = "aa",value = "1a")
@RepeatableAnnotationTest(key = "bb",value = "2b")
public class RepeatableTest {

    public static void main(String[] args) {
        RepeatableAnnotationTest[] annotation = RepeatableTest.class.getAnnotation(MyRepeatableAnnotation.class).value();
        for (RepeatableAnnotationTest a : annotation) {
            System.out.println(a);
        }
    }

}

输出:
@annotation.RepeatableAnnotationTest(key=aa, value=1a)
@annotation.RepeatableAnnotationTest(key=bb, value=2b)

6.@Native注解

@Native注解修饰成员变量,则表示这个变量可以被本地代码引用,常常被代码生成工具使用。对于@Native注解不常使用,了解即可。

2.3、自定义注解


①:@interface是用来声明一个注解的,格式public @interface 注解名{定义内容}
②:其中的每一方法实际上是声明了一个配置参数
③:方法的名称就是参数的名称
④:返回值类型就是参数的类型(返回值类型只能是基本数据类型,Class,String,enum)
⑤:可以通过default来声明参数的默认值
⑥:如果只有一个参数成员,一般参数名称为value
⑦:注解参数必须有值,我们自定义注解元素时,经常使用空字符串,0作为默认值

2.4、自定义注解实现及测试

Controller.annotation:

import java.lang.annotation.*;

/**
 * @author yunyan
 * @date 2023/7/22
 */
//该注解可以应用于类、接口(包括注解类型)、枚举
@Target(ElementType.TYPE)//ElementType.TYPE
//该注解标记的元素可以被Javadoc 或类似的工具文档化
@Documented
//该注解的生命周期,由JVM 加载,包含在类文件中,在运行时可以被获取到
@Retention(RetentionPolicy.RUNTIME)//RUNTIME
public @interface Controller {
    String value() default "";
}

 RequestMapping.annotation:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author yunyan
 * @date 2023/7/22
 */
//该注解的生命周期,由JVM 加载,包含在类文件中,在运行时可以被获取到
@Retention(RetentionPolicy.RUNTIME)
//该注解可以应用于类、接口(包括注解类型)、枚举 以及方法上
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface RequestMapping {

    String value() default "";

    RequestMethod[] method() default {};
}
enum RequestMethod {
    GET, POST
}

TestController.java

import com.qcby.sourcecode.annotation.Controller;
import com.qcby.sourcecode.annotation.RequestMapping;

@Controller
@RequestMapping("test")
public class TestController {
    @RequestMapping
    public  String index(){
        System.out.println("test->index");
        return "";
    }
    @RequestMapping("index1")
    public  String index1(){
        System.out.println("test->index1");
        return "";
    }
}

如果把controller注解在方法上,会报错,原因是我们定义的@controller注解只能写在类、接口、枚举上面。

Main.java 用于将该项目中被标记@Controller注解的类,创建实例并存入一个Map中。

import com.qcby.sourcecode.annotation.Controller;
import com.qcby.sourcecode.annotation.RequestMapping;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 *
 * @author yunyan
 * @date 2023/07/24
 */
public class Main {
    public static List<String>arr= new ArrayList<>();
    public static Map<String,Object>controllerMap = new HashMap<>();
    static {
        String fileName =  "E:\\SpringTest\\src";
        File file = new File(fileName);
        getFilePath(file);

        try {
            chooseController();
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }

    private static void getFilePath(File file) {
        File[] fs = file.listFiles();
        for (File f : fs) {
            if (f.isDirectory()){
                getFilePath(f);
            }
            if (f.isFile()) {
                String filepath = f.toString();
                filepath = filepath.split("src")[1];
                filepath = filepath.substring(1,filepath.length());
                if( filepath.endsWith(".java")) {
                    //把是.java文件的全类名放到arr中
                    arr.add(filepath.replace("\\", ".").replace(".java", ""));
                }
            }
        }
    }

    //查找所有controller,并创建对象装入Map里(“url”:Object)
    private static void chooseController() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        for(String file: arr){
            Class<?> aClass = Class.forName(file);
            if(aClass.isAnnotationPresent(Controller.class)){
                Object o = aClass.getDeclaredConstructor().newInstance();
                RequestMapping annotation = aClass.getAnnotation(RequestMapping.class);
                if(annotation==null){
                    throw  new RuntimeException("没有标记RequestMapping");
                }
                controllerMap.put(annotation.value(),o);
            }
        }
    }
}

结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/785558.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

出现了HTTPSConnectionPool(host=‘huggingface.co‘, port=443)错误的解决方法

在下载huggingface 模型的时候&#xff0c;经常会出现这个错误&#xff0c;HTTPSConnectionPool(host‘huggingface.co’, port443)&#xff0c;即使你已经有了正确的上网姿势。 如在下载Tokenizer的时候&#xff0c;就会出现&#xff1a; tokenizer AutoTokenizer.from_pre…

权智A133P 安卓10移植SPI转串WK2124驱动

硬件连接示意图 主控CPU通过SPI总线与WK2XXX芯相连接。WK2XXX控制4个UART的数据收发。 其中重要的参数有CS片选线和IRQ中断引脚。 LInux串口驱动框架 当WK2XXX驱动在内核注册成功后&#xff0c;会在/dev目录下面生成ttysWK0,ttysWK1,ttysWK2,ttysWK3节点。上层通过open,read,w…

pytest 第三方插件

目录 前言&#xff1a; 顺序执行&#xff1a;pytest-ordering 失败重试&#xff1a;pytest-rerunfailures 并行执行&#xff1a;pytest-xdist 前言&#xff1a; pytest 是一个广泛使用的 Python 测试框架。它具有强大的测试运行器、测试驱动开发和测试结果可视化等功能。除…

《面试1v1》如何能从Kafka得到准确的信息

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

对高校数字化转型的思考

数字新技术与国民经济各产业的融合深化&#xff0c;使行业产业数字化、网络化、全球化、知识化、智能化趋势愈发显著&#xff0c;深刻改变着人的职业生涯、现代社会对人才的需求和新型就业形式&#xff0c;引发教育资源、形态和范式的深刻变革。数字化转型对于提高学校管理效率…

Redis简介、常用命令

目录 一、​​关系数据库​​与非关系型数据库概述 1.1 关系型数据库 1.2 非关系型数据库 二、关系数据库与非关系型数据库区别 2.1 数据存储方式不同 2.2 扩展方式不同 2.3 对事务性的支持不同 三、非关系型数据库产生背景 四、Redis简介 4.1 Redis的单线程模式 4.…

Linux系列---【Ubuntu 20.04安装KVM】

Ubuntu 20.04安装KVM 一、安装kvm 1.安装kvm sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils 2. 将当前用户添加至libvirt 、 kvm组 sudo adduser $USER libvirt sudo adduser $USER kvm 3.验证安装 virsh list --all 4.启动libvert sudo syst…

Jmeter 压测实战:Jmeter 二次开发之自定义函数

目录 1 前言 2 开发准备 3 自定义函数核心实现 3.1 新建项目 3.2 继承实现 AbstractFunction 类 3.3 最终项目结构 4 Jmeter 加载扩展包 4.1 maven 构建配置 4.2 项目打包 4.3 Jmeter 加载扩展包 5 自定义函数调用调试 5.1 打开 Jmeter 函数助手&#xff0c;选择自…

0基础学习VR全景平台篇 第70篇:VR直播-如何设置付费观看、试看

对于拥有优质内容的VR直播&#xff0c;可以通过付费观看的方式进行内容变现&#xff0c;是当下非常流行的商业模式。 付费价格&#xff1e;0时便会自动弹出“试看时间”的设置项。试看时间&#xff1d;0秒时&#xff0c;用户进入直播间需要先付费才可观看&#xff1b;试看时间&…

【JVM】详解JVM的五大内存模型、可能出现的异常以及堆栈引用易错点

文章目录 1、堆(线程共享)2、方法区(线程共享)3、虚拟机栈&#xff08;线程私有&#xff09;4、本地方法栈(线程私有)5、程序计数器(线程私有)6、易错点 源自&#xff1a;深入理解Java虚拟机&#xff1a;JVM高级特性与最佳实践&#xff08;第3版&#xff09; 周志明 1、堆(线程…

Docker 镜像构建 搭建分布式LNMP论坛 实践

地址规划 nginx 172.18.0.10 mysql 172.18.0.20 php 172.18.0.30 宿主机准备 拉取镜像&#xff0c;下面以此镜像为基础 docker pull centos:7 创建自定义网段以便指定 IP 不变动 docker network create --subnet172.18.0.0/16 --opt "com.docker.network.bridge.na…

【计算机网络】计算机网络基础知识总结(秋招篇)

文章目录 前言计算机网络笔记TCP和UDP分别是什么 有什么区别基于TCP UDP这两个协议的上层协议有哪些&#xff1f;TCP和UDP分别在哪些领域被用的多&#xff1f;TCP实现可靠性传输用了哪些技术&#xff1f;&#xff08;TCP如何实现可靠性传输&#xff09;讲一下超时重传和超时定时…

T3/A40i支持Linux-5.10新内核啦,Docker、Qt、Python统统升级!

自2021年创龙科技推出全志国产化率100%的T3/A40i工业核心板后&#xff0c;不到两年时间已超过800家工业客户选择创龙科技T3/A40i平台。随着客户产品的不断升级与迭代&#xff0c;部分“能源电力”、“工业自动化”行业客户对T3/A40i的Linux版本提出了更高要求&#xff0c;主要涉…

Jmeter查看结果树之查看响应的13种详解方法

Jmeter查看结果树查看响应有哪几种方法&#xff0c;可通过左侧面板底部的下拉框选择: 01 Text 查看结果树中请求的默认格式为Text&#xff0c;显示取样器结果、请求、响应数据3个部分内容。 取样器结果&#xff1a; 默认Raw展示&#xff0c;可以切换为Parsed视图&#xff0c…

用i18next使你的应用国际化-Next.js(App router)

安装插件 npm install i18next react-i18next i18next-resources-to-backend1. 目录结构 . └── app└── [lng]├── second-page| └── page.js├── layout.js└── page.jsapp/[lng]/page.js文件&#xff1a; import Link from next/linkexport default funct…

新增WebDB和ChatGPT组件,支持对ChatGPT资产进行纳管,JumpServer堡垒机v3.5.0发布

2023年7月24日&#xff0c;JumpServer开源堡垒机正式发布v3.5.0版本。在这一版本中&#xff0c;新生代数据库连接组件——问题终结者Chen强势来袭&#xff0c;替代原有的OmniDB组件&#xff0c;在兼容旧版本的同时&#xff0c;解决了旧组件性能不足的问题&#xff0c;为用户提供…

Matlab进阶绘图第23期—密度散点图

密度散点图本质上是一种特征渲染的散点图&#xff0c;其颜色表示某一点所在区域的密度信息。 除了作图&#xff0c;密度散点图绘制的关键还在于密度的计算。 当然&#xff0c;不管是作图还是密度的计算&#xff0c;这些在《Matlab论文插图绘制模板》和《Matlab点云处理及可视…

什么是PostgreSQL?简要介绍其主要特点和用途

PostgreSQL是一种开源的关系型数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;它是最强大和广泛使用的开源数据库之一。PostgreSQL的名称起源于其前身&#xff0c;称为"Ingres"项目&#xff0c;后来被命名为Postgres&#xff0c;而PostgreSQL则是它的进一步…

tinkerCAD案例:7.Skull Button 骷髅纽扣

tinkerCAD案例&#xff1a;7.Skull Button 骷髅纽扣 In this lesson you will learn to make a skull shaped button. Let’s get started! 在本课中&#xff0c;您将学习制作一个骷髅形按钮。让我们开始吧&#xff01; 说明 Drag a Cylinder shape to the workplane. 将“圆柱…

ABAP中截取字符串中间位数常规方法

问题&#xff1a;截取字符串“SNTY2TI 071082241AF”中07108&#xff0c;常规字符串截取方法。 这里直接上代码&#xff1a; REPORT zsy_zm_test19. DATA:lv_datum TYPE sy-datum VALUE 20230428,lv_datum2 TYPE sy-datum VALUE 20220522. DATA:lv_num TYPE i. DATA:lv_strin…