java高级:注解

目录

  • 认识注解&自定义注解
  • 元注解
  • 解析注解
  • 注解的应用场景

认识注解&自定义注解

注解和反射一样,都是用来做框架的,我们这里学习注解的目的其实是为了以后学习框架或者做框架做铺垫的。

先来认识一下什么是注解?Java注解是代码中的特殊标记,比如@Override、@Test等,作用是:让其他程序根据注解信息决定怎么执行该程序。

比如:Junit框架的@Test注解可以用在方法上,用来标记这个方法是测试方法,被@Test标记的方法能够被Junit框架执行。
再比如:@Override注解可以用在方法上,用来标记这个方法是重写方法,被@Override注解标记的方法能够被IDEA识别进行语法检查。

注解不光可以用在方法上,还可以用在类上、变量上、构造器上等位置。

上面我们说的@Test注解、@Overide注解是别人定义好给我们用的,将来如果需要自己去开发框架,就需要我们自己定义注解。

自定义注解的格式如下图所示
请添加图片描述

比如:现在我们自定义一个MyTest注解,注意新建的时候不是class了,而是Annotation

public @interface MyTest1{String aaa();//一定要带小括号 前面的public可以不写 默认自动帮你写了boolean bbb() default true;	//default true 表示默认值为true,使用时可以不赋值。String[] ccc();
}

定义好MyTest注解之后,我们可以使用MyTest注解在类上、方法上等位置做标记。注意使用注解时需要加@符号,如下

@MyTest1(aaa="牛魔王",ccc={"HTML","Java"})
public class AnnotationTest1{@MyTest1(aaa="铁扇公主",bbb=false, ccc={"Python","前端","Java"})public void test1(){}
}

注意:注解的属性名如果是value的话,并且只有value没有默认值,使用注解时value名称可以省略。比如现在重新定义一个MyTest2注解

public @interface MyTest2{String value(); //特殊属性int age() default 10;
}

定义好MyTest2注解后,再将@MyTest2标记在类上,此时value属性名可以省略,代码如下

@MyTest2("孙悟空") //等价于 @MyTest2(value="孙悟空")
@MyTest1(aaa="牛魔王",ccc={"HTML","Java"})
public class AnnotationTest1{@MyTest1(aaa="铁扇公主",bbb=false, ccc={"Python","前端","Java"})public void test1(){}
}

到这里关于定义注解的格式、以及使用注解的格式就学习完了。

那注解本质是什么呢?

想要搞清楚注解本质是什么东西,我们可以把注解的字节码进行反编译,给AnnotationTest1类加个main,运行一下,会使用到的注解都编译成class,再使用XJad工具对class进行反编译。经过对MyTest1注解字节码反编译我们会发现:

1.MyTest1注解本质上是接口,每一个注解接口都继承子Annotation接口
2.MyTest1注解中的属性本质上是抽象方法
3.@MyTest1实际上是作为MyTest接口的实现类对象
4.@MyTest1(aaa="孙悟空",bbb=false,ccc={"Python","前端","Java"})里面的属性值,可以通过调用aaa()、bbb()、ccc()方法获取到。 【继续往下看,再解析注解时会用到】

请添加图片描述




接下来我们还需要学习几种特殊的注解

元注解

什么是元注解?元注解是修饰注解的注解。这句话虽然有一点饶,但是非常准确。我们看一个例子

请添加图片描述

接下来分别看一下@Target注解和@Retention注解有什么作用,它们都是用来修饰Test注解的元注解

@Target是用来声明注解只能用在哪些位置,比如:类上、方法上、成员变量上等
@Retention是用来声明修饰的注解保留周期,比如:源代码时期、字节码时期、运行时期

请添加图片描述

比如我们定义MyTest3注解时,使用@Target注解属性值写成下面样子,加上@Retention则可以决定MyTest3的保留周期,比如我们经常用到的@Test就是保留到运行阶段的,可以点进源码看一下。

//声明@MyTest3注解只能用在类上和方法上
@Target({ElementType.TYPE,ElementType.METHOD})	
public @interface MyTest3{}



解析注解

通过前面的学习我们能够自己定义注解,也能够把自己定义的注解标记在类上或者方法上等位置,但是总感觉有点别扭,给类、方法、变量等加上注解后,我们也没有干什么呀!!!

接下来,我们就要做点什么。我们可以通过反射技术把类上、方法上、变量上的注解对象获取出来,然后通过调用方法就可以获取注解上的属性值了。我们把获取类上、方法上、变量上等位置注解及注解属性值的过程称为解析注解

解析注解套路如下

1.如果注解在类上,先获取类的字节码对象,再获取类上的注解
2.如果注解在方法上,先获取方法对象,再获取方法上的注解
3.如果注解在成员变量上,先获取成员变量对象,再获取变量上的注解
总之:注解在谁身上,就先获取谁,再用谁获取谁身上的注解

请添加图片描述

来看一个案例,来演示解析注解的代码编写

请添加图片描述

按照需求要求一步一步完成

① 先定义一个MyTest4注解

//声明@MyTest4注解只能用在类上和方法上
@Target({ElementType.TYPE, ElementType.METHOD})
//控制使用了@MyTest4注解的代码中,@MyTest4保留到运行时期
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest4{String value();double aaa() default 100;String[] bbb();
}

② 定义一个类Demo

@MyTest4(value="蜘蛛侠",aaa=99.9, bbb={"至尊宝","牛马"})
public class Demo{@MyTest4(value="孙悟空",aaa=199.9, bbb={"紫霞","牛夫人"})public void test1(){}
}

③ 写一个测试类AnnotationTest3解析Demo类上的MyTest4注解

public class AnnotationTest3{@Testpublic void parseClass(){//1.先获取Class对象Class c = Demo.class;//2.解析Demo类上的注解if(c.isAnnotationPresent(MyTest4.class)){//获取类上的MyTest4注解MyTest4 myTest4 = (MyTest4)c.getDeclaredAnnotation(MyTest4.class);//获取MyTests4注解的属性值System.out.println(myTest4.value());System.out.println(myTest4.aaa());System.out.println(Arrays.toString(myTest4.bbb()));}}@Testpublic void parseMethods() throws NoSuchMethodException {//1.先获取Class对象Class c = Demo.class;//2.解析Demo类中test1方法上的注解MyTest4注解Method m = c.getDeclaredMethod("test1");if(m.isAnnotationPresent(MyTest4.class)){//获取方法上的MyTest4注解MyTest4 myTest4 = (MyTest4)m.getDeclaredAnnotation(MyTest4.class);//获取MyTests4注解的属性值System.out.println(myTest4.value());System.out.println(myTest4.aaa());System.out.println(Arrays.toString(myTest4.bbb()));}}
}

运行测试类,parseClass()的运行结果如下:

请添加图片描述

parseMethods()的运行结果如下:

请添加图片描述




注解的应用场景

关于注解的定义、使用、解析注解就已经学习完了。接下来,我们再学习一下注解的应用场景,注解是用来写框架的,比如现在我们要模拟Junit写一个测试框架,要求有@MyTest注解的方法可以被框架执行,没有@MyTest注解的方法不能被框架执行。

第一步:先定义一个MyTest注解

@Target(ElementType.METHOD)	
@Retetion(RetetionPloicy.RUNTIME)
public @interface MyTest{}

第二步:写一个测试类AnnotationTest4,在类中定义几个被@MyTest注解标记的方法

public class AnnotationTest4{@MyTestpublic void test1(){System.out.println("=====test1====");}@MyTestpublic void test2(){System.out.println("=====test2====");}public void test3(){System.out.println("=====test2====");}public static void main(String[] args){AnnotationTest4 a = new AnnotationTest4();//1.先获取Class对象Class c = AnnotationTest4.class;//2.解析AnnotationTest4类中所有的方法对象Method[] methods = c.getDeclaredMethods();for(Method m: methods){//3.判断方法上是否有MyTest注解,有就执行该方法if(m.isAnnotationPresent(MyTest.class)){m.invoke(a);}}}
}

运行结果:

=====test2====
=====test1====

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

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

相关文章

嵌入式学习笔记(31)异常向量表的编程处理

6.5.1像内存一样去访问异常向量表 (1)S5PV210的异常向量表可以改变(在CP15协处理器中),以适应操作系统的需求。但是目前系统刚启动,此时DRAM尚未初始化,程序哦都市在iSRAM中运行。210在iSRAM中…

C++下基于粒子群算法解决TSP问题

粒子群优化算法求解TSP旅行商问题C(2020.11.12)_jing_zhong的博客-CSDN博客 混合粒子群算法(PSO):C实现TSP问题 - 知乎 (zhihu.com) 一、原理 又是一个猜答案的算法,和遗传算法比较像,也是设…

入门人工智能 ——自然语言处理介绍,并使用 Python 进行文本情感分析(5)

入门人工智能 ——自然语言处理介绍,并使用 Python 进行文本情感分析(5)) 入门人工智能 ——自然语言处理介绍,并使用 Python 进行文本情感分析介绍自然语言处理的挑战NLP的基本任务NLP的基本技术NLP的应用领域 使用 P…

FPGA的基础架构,什么是CLB?

本原创文章由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处 CLB是指可编程逻辑功能块(Configurable Logic Blocks),顾名思义就是可编程的数字逻辑电路。CLB是FPGA内的三个基本逻辑单元。C…

与社交媒体结合:视频直播美颜sdk在社交平台上的应用

为了让直播内容更吸引人,视频直播美颜sdk(Software Development Kit)正逐渐崭露头角,为社交媒体用户提供了卓越的美颜效果和互动体验。 一、什么是视频直播美颜sdk? 在深入讨论如何将视频直播美颜sdk整合到社交媒体平…

CSS元素浮动

概述 浮动简介 在最初,浮动是用来实现文字环绕图片效果的,现在浮动是主流的页面布局方式之一。 元素浮动后的特点 脱离文档流。不管浮动前是什么元素,浮动后,默认宽与高都是被内容撑开的(尽可能小)&am…

时序分解 | MATLAB实现基于小波分解信号分解分量可视化

时序分解 | MATLAB实现基于小波分解信号分解分量可视化 目录 时序分解 | MATLAB实现基于小波分解信号分解分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于小波分解的分量可视化,MATLAB编程程序,用于将信号分解成不同尺度和频率的子信…

实用技巧:Linux上实现OpenGauss数据库远程连接,方便的跨网络数据操作

文章目录 前言1. Linux 安装 openGauss2. Linux 安装cpolar3. 创建openGauss主节点端口号公网地址4. 远程连接openGauss5. 固定连接TCP公网地址6. 固定地址连接测试 🍁 小结 🍁 前言 openGauss是一款开源关系型数据库管理系统,采用木兰宽松许…

Spring-MVC使用JSR303及拦截器,增强网络隐私安全

目录 一、JSR303 ( 1 ) 是什么 ( 2 ) 作用 ( 3 ) 常用注解 ( 4 ) 入门使用 二、拦截器 2.1 是什么 2.2 拦截器与过滤器的区别 2.3 应用场景 2.4 基础使用 2.5 用户登录权限控制 给我们带来的收获 一、JSR303 ( 1 ) 是什么 JSR 303是Java规范请求&#xff…

进程间通信——共享内存

目录 共享内存的原理 共享内存通信的实现步骤 通信实例 共享内存的原理 原理:可以说,共享内存是一种最为高效的进程间通信方式。因为进程可以直接读写内存,不需要任何数据的复制。为了在多个进程间交换信息,内核专门留出一块内…

C语言 —— 初步入门知识(第一个C语言程序、数据类型、变量常量、字符与注释)

本篇文章介绍C语言的基础知识,使读者对C语言能够有一个大概的认识. 不会细写每一个知识点, 但是能够入门C语言, 进行初步的C语言代码阅读. 首先, 什么是语言? 对于人和人之间进行交流的语言, 我们知道, 可以通过汉语, 英语, 日语等语言进行交流. 那么对于人和计算…

计算机网络:三次握手与四次挥手

摘取作者:拓跋阿秀 三次握手 三次握手(Three-way Handshake)其实就是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后…

SpringMVC系列(四)之SpringMVC实现文件上传和下载

目录 前言 一. SpringMVC文件上传 1. 配置多功能视图解析器 2. 前端代码中,将表单标记为多功能表单 3. 后端利用MultipartFile 接口,接收前端传递到后台的文件 4. 文件上传示例 1. 相关依赖: 2. 逆向生成对应的类 3. 后端代码&#xf…

(10)(10.9) 术语表(一)

文章目录 前言 1 2.4Ghz 2 AGL 3 AHRS 4 APM 5 AMA 6 Arduino 7 APM (AutoPilot Mega) 8 ATC 9 Copter 10 Plane 11 Rover 12 BEC 13 Bootloader 14 COA 15 DCM 16 Eagle file 17 ESC 18 Firmware 19 FPV 20 FTDI 前言 !Note 术语表未编入索…

微信小程序学习笔记1.0

第1章 微信小程序基础 1.1 微信小程序介绍 1.1.1 什么是微信小程序 微信小程序的特点: ① 微信小程序是不需要下载和安装的; ② 它可以完成App应用软件的交互功能; ③ 用户扫一扫或者搜一下就可以使用小程序; ④ 微信小程序…

Python模板注入(SSTI)

概念 发生在使用模板引擎解析用户提供的输入时。模板注入漏洞可能导致攻击者能够执行恶意代码或访问未授权的数据。 模板引擎可以让(网站)程序实现界面与数据分离,业务代码与逻辑代码分离。即也拓宽了攻击面,注入到模板中的代码可…

数据库逻辑透明-架构真题(二十九)

(2020年)假设某计算机字长为32位,该计算机文件管理系统磁盘空间管理采用位示图(bitmap)记录磁盘的使用情况。若磁盘的容量为300GB,物理块大小为4MB,那么位示图的大小为()…

海外媒体发稿:海外汽车媒体推广9个方式解析

根据下列9个国外汽车媒体推广方式,企业能够在国际范围内突破边界,获得领域关心。这将帮助企业完成国际化发展发展战略,扩展市场占有率和提升盈利空间。【华媒舍】国外全媒体发表文章将会成为企业完成这一目标的重要方式,为企业带来…

Java中的异常基础知识

目录 什么是异常? 1.算术异常 2.数组越界异常 3.空指针异常 4.输入不匹配异常 Java异常体系 异常的处理 防御式编程: 事后认错 异常处理流程 自定义异常 什么是异常? 在Java中,将程序执行过程中发生的不正常行为称为异常 1.算术异常 public static void main(St…

GDB之保存已经设置的断点(十六)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…