Java基础回顾——注解

文章目录

  • 介绍
  • 定义注解
  • 处理注解
  • 使用注解

介绍

注解Annotation:是放在Java源码的类、方法、字段、参数前的一种特殊注释

注释会被编译器直接忽略,注解则可以被编译器打包进入class文件,因此,注解是一种用作标注的“元数据”。

作用
1、编译器使用的注解
不会被编译进入.class文件,在编译后就被编译器扔掉了

例子:

@Override:让编译器检查该方法是否正确地实现了覆写;
@SuppressWarnings:告诉编译器忽略此处代码产生的警告。

2、由工具处理.class文件使用的注解

3、在程序运行期能够读取的注解,它们在加载后一直存在于JVM中,这也是最常用的注解。

定义注解时,可以定义配置参数,可以有默认值。

public class Hello {@Check(min=0, max=100, value=55)public int n;@Check(value=99)public int p;@Check(99) // @Check(value=99)public int x;@Checkpublic int y;
}

定义注解

使用@interface语法来定义注解(Annotation)

public @interface Report {int type() default 0;String level() default "info";String value() default "";
}

元注解
作用:修饰其他注解。

Java中已经定义了一些元注解。

常用的:

1、@Target

使用@Target可以定义Annotation能够被应用于源码的哪些位置:

  • 类或接口:ElementType.TYPE;
  • 字段:ElementType.FIELD;
  • 方法:ElementType.METHOD;
  • 构造方法:ElementType.CONSTRUCTOR;
  • 方法参数:ElementType.PARAMETER。
@Target(ElementType.METHOD)
public @interface Report {int type() default 0;String level() default "info";String value() default "";
}@Target({ElementType.METHOD,ElementType.FIELD
})
public @interface Report {...
}

2、@Retention

@Retention定义了Annotation的生命周期:

  • 仅编译期:RetentionPolicy.SOURCE;
  • 仅class文件:RetentionPolicy.CLASS;
  • 运行期:RetentionPolicy.RUNTIME。

如果@Retention不存在,则该Annotation默认为CLASS。

3、@Repeatable

@Repeatable可以定义Annotation是否可重复。

4、@Inherited
@Inherited定义子类是否可继承父类定义的Annotation。

@Inherited仅针对@Target(ElementType.TYPE)类型的annotation有效,并且仅针对class的继承,对interface的继承无效

@Inherited
@Target(ElementType.TYPE)
public @interface Report {int type() default 0;String level() default "info";String value() default "";
}

定义Annotation步骤:

1、用@interface定义注解

2、添加参数,默认值

3、用元注解配置注解

其中,必须设置@Target和@Retention,@Retention一般设置为RUNTIME

处理注解

根据@Retention的配置:

  • SOURCE类型的注解在编译期就被丢掉了;
  • CLASS类型的注解仅保存在class文件中,它们不会被加载进JVM;
  • RUNTIME类型的注解会被加载进JVM,并且在运行期可以被程序读取。

SOURCE类型的注解主要由编译器使用,一般只使用,不编写。CLASS类型的注解主要由底层工具库使用,涉及到class的加载,一般很少用到。只有RUNTIME类型的注解不但要使用,还经常需要编写。

读取RUNTIME类型注解

注解定义后也是一种class,所有的注解都继承自java.lang.annotation.Annotation,读取注解,需要使用反射API

Java提供的使用反射API读取Annotation的方法包括:

判断某个注解是否存在于Class、Field、Method或Constructor:

  • Class.isAnnotationPresent(Class)
  • Field.isAnnotationPresent(Class)
  • Method.isAnnotationPresent(Class)
  • Constructor.isAnnotationPresent(Class)

使用反射API读取Annotation:

  • Class.getAnnotation(Class)
  • Field.getAnnotation(Class)
  • Method.getAnnotation(Class)
  • Constructor.getAnnotation(Class)

使用反射API读取Annotation有两种方法。方法一是先判断Annotation是否存在,如果存在,就直接读取:

Class cls = Person.class;
if (cls.isAnnotationPresent(Report.class)) {Report report = cls.getAnnotation(Report.class);...
}

第二种方法是直接读取Annotation,如果Annotation不存在,将返回null:

Class cls = Person.class;
Report report = cls.getAnnotation(Report.class);
if (report != null) {...
}

要读取方法参数的注解,我们先用反射获取Method实例,然后读取方法参数的所有注解:

public void hello(@NotNull @Range(max=5) String name, @NotNull String prefix) {
}// 获取Method实例:
Method m = ...
// 获取所有参数的Annotation:
Annotation[][] annos = m.getParameterAnnotations();
// 第一个参数(索引为0)的所有Annotation:
Annotation[] annosOfName = annos[0];
for (Annotation anno : annosOfName) {if (anno instanceof Range r) { // @Range注解r.max();}if (anno instanceof NotNull n) { // @NotNull注解//}
}

使用注解

例子:

写一个@Range注解,希望用它来定义一个String字段的规则:字段长度满足@Range的参数定义:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Range {int min() default 0;int max() default 255;
}

在某个JavaBean中,可以使用该注解:

public class Person {@Range(min=1, max=20)public String name;@Range(max=10)public String city;
}

但是,定义了注解,本身对程序逻辑没有任何影响。必须自己编写代码来使用注解。这里,编写一个Person实例的检查方法,它可以检查Person实例的String字段长度是否满足@Range的定义:

void check(Person person) throws IllegalArgumentException, ReflectiveOperationException {// 遍历所有Field:for (Field field : person.getClass().getFields()) {// 获取Field定义的@Range:Range range = field.getAnnotation(Range.class);// 如果@Range存在:if (range != null) {// 获取Field的值:Object value = field.get(person);// 如果值是String:if (value instanceof String s) {// 判断值是否满足@Range的min/max:if (s.length() < range.min() || s.length() > range.max()) {throw new IllegalArgumentException("Invalid field: " + field.getName());}}}}
}

例子
只看不知道具体怎么写,就看着敲了一遍

Range.java

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Range {int min() default 0;int max() default 255;
}

Animal.java

public class Animal {@Range(min = 2, max =20)public String name;@Range(min = 0, max =8)public int number;public Animal(String name,int number) {this.name = name;this.number = number;}
}

TestAnnotation2.java

import java.lang.reflect.Field;public class TestAnnotation2 {public static void main(String[] args) throws ReflectiveOperationException {Animal animal=new Animal("1",10);check(animal);}static  void check(Animal person) throws IllegalArgumentException,ReflectiveOperationException{for(Field field : person.getClass().getFields()){Range range=field.getAnnotation(Range.class);if(range!=null){Object value=field.get(person);if(value instanceof String){if (((String) value).length() < range.min() || ((String) value).length() > range.max()) {System.out.println("Invalid field: " + field.getName());}}if(value instanceof Integer){if ((int)value < range.min() || (int)value > range.max()) {System.out.println("Invalid field: " + field.getName());}}}}}
}

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

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

相关文章

PHP HTTPoxy CGI 应用程序漏洞 CVE-2016-5385

HTTPoxy CGI 应用程序漏洞 CVE-2016-5385 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建漏洞利用 修复建议 漏洞名称 漏洞描述 在Oracle Communications BRM 10.x/12.x&#xff08;云软件&#xff09;中发现漏洞。它已经被宣布为关键。此漏洞影响组件用户数据库的未…

Linux笔记---用户和权限管理基本命令介绍

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Linux学习 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 ​编辑 前言&#xff1a; 命令&#xff1a; whoami&#xff1a; passwd&#xff1a; useradd&#xff1a; userdel&#xff1a; chm…

华为交换配置OSPF与BFD联动

实验拓扑 组网需求 如图所示&#xff0c;SW1、SW2和SW3之间运行OSPF&#xff0c;SW1和SW2之间的交换机仅作透传功能。现在需要SW1和SW2能够快速感应它们之间的链路状态&#xff0c;当链路SW1-SW2发生故障时&#xff0c;业务能快速切换到备份链路SW1-SW3-SW2上 配置思路 采用…

文件的基本管理

目录 一、Linux系统目录结构和相对/绝对路径 &#xff08;一&#xff09;系统目录结构 &#xff08;二&#xff09;相对路径和绝对路径 1.绝对路径 2.相对路径 &#xff08;三&#xff09;通配符的作用 二、创建、复制、删除文件&#xff0c;rm -rf /意外事故 &#xf…

说说对React Hooks的理解?解决了什么问题?

面试官&#xff1a;说说对React Hooks的理解&#xff1f;解决了什么问题&#xff1f; 一、是什么 Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性 至于为什么引入hook&#xff0c;官方给出的动机是解决长时间使用和维护…

山景DU561—32位高性能音频处理器(DSP)芯片

音频处理可以更好地捕捉和处理声音和音乐&#xff1b;而DSP音频处理芯片是一种利用数字信号处理技术进行音频处理的专用芯片&#xff1b;可用于多种应用&#xff0c;从音乐拾音到复杂的音频信号处理&#xff0c;和声音增强。 由工采网代理的山景DU561是一款集成多种音效算法高…

C# 获取本机IP地址的方法

在C#环境中&#xff0c;要获取本机的IP地址&#xff0c;可以使用以下方法&#xff1a; 1、使用NetworkInterface类和IPAddress类&#xff1a; using System; using System.Net; using System.Net.NetworkInformation;class Program {static void Main(){// 获取本地计算机上的…

08、基于LunarLander登陆器的DDQN强化学习(含PYTHON工程)

08、基于LunarLander登陆器的DDQN强化学习&#xff08;含PYTHON工程&#xff09; LunarLander复现&#xff1a; 07、基于LunarLander登陆器的DQN强化学习案例&#xff08;含PYTHON工程&#xff09; 08、基于LunarLander登陆器的DDQN强化学习&#xff08;含PYTHON工程&#xf…

登录注册表单路由切换 - 登录注册开发入门(6)

登录注册表单路由切换 - 登录注册开发入门(6) 教程目标 完成注册表单的搭建&#xff0c;并实现与登录表单的无缝切换。 教程步骤 创建路由容器 在页面中添加一个路由容器。路由容器需要与路由的页面容器配合使用。 添加页面组件 在路由容器下方添加两个页面组件&#xff0c;…

普通虚拟主机如何安装SSL证书?

在今天的互联网世界中&#xff0c;保护网站数据安全和用户隐私已经成为了每个网站拥有者的重要任务。尽管安装SSL证书在普通虚拟主机环境中可能会有一些挑战&#xff0c;但通过正确的步骤和配置&#xff0c;您仍然可以为您的网站提供更高级别的安全保护。普通虚拟主机如何安装S…

DTC营销新模式,创新商业引领裂变营销新潮流的玩法!

DTC营销新模式&#xff0c;创新商业引领裂变营销新潮流的玩法&#xff01; 随着市场竞争的加剧&#xff0c;企业寻求创新的营销模式以突破困境&#xff0c;脱颖而出。其中&#xff0c;DTC&#xff08;Direct-to-Consumer&#xff0c;直接面向消费者&#xff09;营销新模式应运…

【mysql】MySql中死锁是什么?怎么解决?

在MySQL中,死锁是指两个或多个事务相互等待对方持有的资源,导致它们无法继续执行并永远地被阻塞的情况。每个事务都持有一些资源,并且等待其他事务释放资源,但由于循环依赖关系,导致所有事务都无法继续执行,从而形成死锁。 当发生死锁时,MySQL会自动检测到它,并选择其…

CentOS 7 制作openssh 9.6 rpm包更新修复安全漏洞 —— 筑梦之路

2023年12月18日 openssh 发布新版9.6p1&#xff0c;详细内容阅读OpenSSH: Release Notes 背景说明 之前也写过多篇制作openssh rpm包的文章&#xff0c;为何要重新来写一篇制作openssh 9.6版本的&#xff1f; openssh 9.6 rpm包制作和之前存在区别&#xff0c;对于CentOS 7来…

spring之面向切面:AOP(2)

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

【Python】函数

一、函数介绍 二、函数的定义 三、函数的参数 四、函数的返回值 五、函数说明文档 六、函数的嵌套调用 七、变量的作用域 一、函数介绍 函数的使用 函数的作用 函数 函数&#xff1a;是组织好的&#xff0c;可重复使用的&#xff0c;用来实现特定功能的代码段。 input()、p…

文件批量管理,按单值大小归类保存,提升工作效率与便捷性!

你是否曾经遇到过需要批量管理大量文件&#xff0c;但却因为文件大小不一而感到混乱&#xff1f;你是否希望有一种方法能够将这些文件按照单值大小进行归类保存&#xff0c;以便更方便地管理和查找&#xff1f;现在&#xff0c;我们有一个好消息要告诉你&#xff0c;我们推出了…

Nvm切换nodejs版本

下载地址 Releases coreybutler/nvm-windows GitHub 安装运行 双击安装运行即可 下载速度慢的&#xff0c;可以通过修改配置文件切换国内下载镜像 node_mirror: https://npm.taobao.org/mirrors/node/ npm_mirror: CNPM Binaries Mirror 打开安装目录&#xff0c;修改se…

【个人记录】Ubuntu做网络路由+强化学习项目debug

本篇并不介绍做整个项目的过程&#xff0c;仅仅是个人在科研过程中的debug记录和心得。希望某个部分是你正需要的解决方案。 第一部分&#xff1a;在服务器上安装mininet mininet是一个在安装过程中比较容易出问题的包。一定要好好看看官方INSTALL文档。Download/Get Started…

easyExcel生成excel并导出自定义样式------添加复杂表头

easyExcel生成excel并导出自定义样式------添加复杂表头 设置合并竖行单元格&#xff0c;表头设置 OutputStream outputStream ExcelUtils.getResponseOutputStream(response, fileName);//根据数据组装需要合并的单元格Map<String, List<String>> strategyMap …

gem5 garnet l1 l2 cache的创建与相连

gem5 garnet l1 l2 cache的创建与相连 主要就是这个图&#xff1a; 细节 我们用的是gem5/configs/deprecated/example/fs.py #fs.py 引入了上两层路径&#xff0c;也就是当前可以看到 gem5/configs/路径。 addToPath("../../")#fs.py引入了gem5/configs/ruby/Ru…