注解(概念、分类、自定义注解)

注解基本概念

注解(元数据)为我们在代码中添加信息提供一种形式化的方法,我们可以在某个时刻非常方便的使用这些数据。将的通俗一点,就是为这个方法增加的说明或功能。

作用:

  1. 编写文档:通过代码里标识的注解生成文档【生成doc文档】
  2. 代码分析:通过代码里的标识的注解对代码进行分析【使用反射】
  3. 编译检查:通过代码里的标识的注解让编译器实现基本的编译检查

JDK提供的注解

Java目前内置了三种注解@Override、@Deprecated、@SuppressWarnnings

@Override:用于标识方法,标识该方法属于重写父类的方法

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

@Deprecated:用于标识方法或类,标识该类或方法已过时,建议不要使用

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

@SuppressWarnnings:用于有选择的关闭编译器对类、方法、成员变量、变量初始化的警告(压抑警告)

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}

元注解

Java提供了四种元注解,即修饰注解的注解。观察上面源码可以发现三种,即:@Target、@Retention、@Document、@Inherited。主要作用如下:

名称

作用

属性值

取值

@Target

标识该注解用于什么地方

ElementType

CONSTRUCTOR:构造器上声明

FILED:属性上声明

LOCAL_VARIABLE:局部变量上声明

METHOD:方法上声明

PACKAGE:包声明

TYPE:类、接口、enum上使用

@Retention

表示在注解保留的阶段

RetentionPolicy

SOURCE:注解在编译时丢掉

CLASS:注解在class文件中存在,但会被jvm丢弃

RUNTIME:jvm会保留注释,可以通过反射机制获取注解信息

@Document

描述注解是否被抽取到API文档

@Inherited

允许子类继承父类的注解

如何自定义注解

使用@interface定义注解,会自动继承java.lang.annotation.Annotation接口,类似于类自动继承Object一样。注解中的每个方法表示一个配置参数,返回类型即是参数类型,可以通过default标识参数默认值。

本质:就是一个接口默认继承java.lang.annotation.Annotation接口

定义方式如下:

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)//十分重要
@Target(ElementType.METHOD)
public @interface Test {
String value() default "";
}

注解中的参数类型

注解中的参数只支持如下类型:

  • 所有的基本类型:byte、short、char、int、long、float、double
  • String类型
  • Class类型
  • enum类型
  • Annotation类型
  • 以上类型的数组

如果定义其他类型的参数编译器会报错。


 

使用注解的注意点

  • 如果注解只有一个参数,最好取名value,这样在使用的时候可以直接指定属性值。例如:@Test("hello")
  • 只能使用public和默认权限修饰符修饰参数
  • 参数默认值:注解参数必须有确定的值。要么在定义的时候给默认值;要么在使用注解的时候指定参数值。
  • 赋值时,如果只有一个属性,且属性名是value,则value可以省略,直接定义值即可。,数组赋值时,值用{ }包裹,但是数组只有一个值时,则{ }可以省略

注解处理器

如果没有读取注解的方法,那么该注解就没有任何意义。使用注解的过程中,注解处理器是必不可少的,Java反射机制,完成对注解的处理

注解处理器类库

Java通过反射机制获取类、方法、属性上的注解,因此java.lang.reflect提供AnnotationElement支持注解,主要方法如下:

boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判断该元素是否被annotationClass注解修饰
<T extends Annotation> T getAnnotation(Class<T> annotationClass):获取 该元素上annotationClass类型的注解,
如果没有返回null(//    其实就是在内存中生成一个该注释接口的子类实现对象)
Annotation[] getAnnotations():返回该元素上所有的注解
<T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass):返回该元素上指定类型所有的注解
Annotation[] getDeclaredAnnotations():返回直接修饰该元素的所有注解
<T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass):返回直接修饰该元素的所有注解

 

 总测试源码:每个分割是一个类

@Retention(RetentionPolicy.RUNTIME) //一定要加这个注解(注解的保留阶段)
public @interface WebServlet2 {public String value() default "";public String url() default "";public String name() default "";}/***************/
@WebServlet2(url = "/load3",name = "无语")
public class demo3 {void show(){System.out.println("我是demo3");}}/***************/
@WebServlet2(url = "/load")
public class demo2 {void show(){System.out.println("我是demo2");}
}/***************/
@WebServlet2(url = "/load")
public class demo1 {void show(){System.out.println("我是demo1");}}
/***************/package com.aqiuo.反射;import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class SumDemo {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {String arr[] =new String[]{"com.aqiuo.反射.demo1","com.aqiuo.反射.demo2","com.aqiuo.反射.demo3","com.aqiuo.反射.Person"};String urlname="/load";Class[] cls=new Class[arr.length];for (int i=0;i<arr.length;i++) {cls[i]=Class.forName(arr[i]);WebServlet2 annotation= (WebServlet2) cls[i].getDeclaredAnnotation(WebServlet2.class);if(annotation!=null) {String url = annotation.url();if (url.equals(urlname)) {System.out.println(arr[i]);Object x = cls[i].newInstance();Method method = cls[i].getDeclaredMethod("show");method.invoke(x);}}}}
}

 

小结:

  1. 以后大多数时候,我们会使用注解,而不是自定义注解
  2. 注解给谁看:
    1. 编译器
    2. 解析程序
  3. 注解不是程序的一部分

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

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

相关文章

uniapp 页面回退逻辑梳理

在uniapp 开发项目&#xff0c;有时在同一个页面 回退 会有不同的要求&#xff0c;无法通用的用navigaBack去解决 因此 这时候 就可以使用onBackPress方法&#xff0c;根据不同的参数条件来控制回退的页面

【软件测试学习】—软件测试模型(二)

【软件测试学习】—软件测试模型&#xff08;二&#xff09; 我 | 在这里 &#x1f469;‍&#x1f9b0;&#x1f469;‍&#x1f9b0; 读书 | 长沙 ⭐计算机科学与技术 ⭐ 本科 【2024届】 &#x1f383;&#x1f383; 爱好 | 旅游、跑步、网易云、美食、摄影 &#x1f396;️…

【MYSQL】表的基本查询

目录 前言 一、Create&#xff08;增&#xff09; 1.单行数据 全列插入 2.多行数据 指定列插入 3.插入否则更新 4.替换 二、Retrieve&#xff08;查&#xff09; 1.select列 1.1全列查询 1.2指定列查询 1.3查询字段为表达式 1.4为查询结果指定别名 1.5结果去重 …

C++基础 -18-继承中类继承的区别

无论使用公有&#xff0c;保护&#xff0c;私有继承 都无法访问基类私有成员 在多级继承中 使用公有继承 派生的派生可以访问基类的公有&#xff0c;保护成员 在多级继承中 使用保护继承 派生的派生可以访问基类的公有&#xff0c;保护成员 在多级继承中 使用私有继承 派生的派…

03、K-means聚类实现步骤与基于K-means聚类的图像压缩(2)

03、K-means聚类实现步骤与基于K-means聚类的图像压缩&#xff08;2&#xff09; 工程下载&#xff1a;K-means聚类实现步骤与基于K-means聚类的图像压缩 其他&#xff1a; 03、K-means聚类实现步骤与基于K-means聚类的图像压缩&#xff08;1&#xff09; 03、K-means聚类实现…

删除排序链表的重复元素I和II,多种解法和思考

删除排序链表的重复元素I https://leetcode.cn/problems/remove-duplicates-from-sorted-list/description/ 一个循环就可以了&#xff0c;如果当前节点和下一个节点值一样&#xff0c;当前节点不移动让next后移动一个&#xff0c;如果不一样则当前节点后移。 一个循环就可以…

Testlink 1.9.20+phpstudy_pro安装遇到的问题

phpstudy_pro启动了Apache2.4.39和Mysql5.7.26,php的版本是7.3.4zai。 安装Testlink 1.9.19时没有数据库的问题&#xff0c;安装Testlink 1.9.20时遇到了数据库问题&#xff0c;如下图所示&#xff1a; 网上搜索“Failed!Mysql Database cannnot be used”&#xff0c;给出的…

Python接口自动化测试如何设计接口测试用例(详解)

简介 上篇我们已经介绍了什么是接口测试和接口测试的意义。在开始接口测试之前&#xff0c;我们来想一下&#xff0c;如何进行接口测试的准备工作。或者说&#xff0c;接口测试的流程是什么&#xff1f;有些人就很好奇&#xff0c;接口测试要流程干嘛&#xff1f;不就是拿着接口…

Java高级技术(动态代理)

一&#xff0c;代理 二&#xff0c;案例 放到代码中演示&#xff1a; 首先&#xff0c;创建一个明星接口&#xff0c;这个接口有一个skill方法&#xff0c;说明只要是明星就必须有点技能。 public interface Star {void skill(); } 然后&#xff0c;创建坤坤对象&#xff0c…

第一个C代码讲解

文章目录 编写C文件创建文本文件编写代码修改文件后缀切换文件路径 编译代码打开命令行使用gcc编译代码运行程序双击运行使用命令行运行 代码分析编译过程 编写C文件 编辑C代码文件的工具有很多&#xff0c;为了让大家初学的时候摆脱编译软件的干扰&#xff0c;更容易理解编译过…

JVM——产生内存溢出原因

目录 1.产生内存溢出原因一 &#xff1a;代码中的内存泄漏1.案例1&#xff1a;equals()和hashCode()导致的内存泄漏问题&#xff1a;**正常情况**&#xff1a;**异常情况&#xff1a;**解决方案&#xff1a; 2.案例2&#xff1a;内部类引用外部类问题&#xff1a;解决方案&…

VSCODE+QEMU+WSL调试RISCV代码(SBI、kernel)

前言 最近在对RISC-V架构比较感兴趣&#xff0c;正好手头有《RISC-V体系结构编程与实践》的书籍&#xff0c;就打算跟随笨叔将这块的知识学习起来&#xff0c;最开始当然是需要搭建一个基础的实验平台&#xff0c;本来笨叔是贴心的提供了VMare的环境&#xff0c;奈何天生叛逆的…