Java注解及自定义注解

news2024/11/17 11:54:04

注解/元数据(Annotation),是对代码级别的说明;在JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明、注释;主要可以用于创建文档,跟踪代码中的依赖性,执行基本编译时检查;注解是以‘@注解名’在代码中存在的,根据注解参数的个数,我们可以将注解分为:标记注解、单值注解、完整注解三类;它们都不会直接影响到程序的语义,只是作为标识存在,可以通过反射机制实现对这些元数据(用来描述数据的数据)的访问并且可以在编译时选择代码里的注解是否只存在于源码级,或者也能在class文件、或者运行时中出现(SOURCE/CLASS/RUNTIME)。

一、按照作用Annotation有三种作用

1、编写文档(文档注解):通过代码里标识的注解生成文档【生成doc文档,通过 javadoc 类文件名称 的方式生成对应的html文档,文档中会将文档注解进行解析生成内容】

编写类文件,并使用文档注解进行标注:
在这里插入图片描述
使用 javadoc 类文件名称 进行生成文档(这一步可能会报错 错误: 编码GBK的不可映射字符 ,原因是 java程序在编译的时候,需要使用JDK开发工具包中的JAVAC.EXE命令,默认编码格式为UNICODE,而我们的代码并非这个编码格式,解决方案是比如使用 notepad++ 编写Java代码前,先将Java文件的编码格式改为 ANSI编码格式 ,然后编写代码并保存,重新执行javadoc即可(如果没有报错但生成的文档打开中文乱码也可以采用该方法解决)):
在这里插入图片描述
在这里插入图片描述
打开 index.html 文件如下:
在这里插入图片描述
2、代码分析(功能注解):通过代码里标识的注解对代码进行分析【使用反射实现该功能,最重要的功能】
3、编译检查(编译验证注解):通过代码里标识的注解让编译器能够实现基本的编译检查【如:Override,表示这个方法是对父类方法的重写,如果被@Override注解标记的方法父类不存在该方法,那么编译无法通过、编码软件也会提示错误】
在这里插入图片描述

二、Java常见内置注解

1、@Override:作用是对覆盖超类中方法的方法进行标记,如果被标记的方法并没有实际覆盖超类中的方法,则编译器会发出错误警告。
2、@Deprecated:作用是对不应该再使用的方法进行标记(标记方法过时,比如有新版本的方法之后不建议使用以前版本的方法),使用这些方法时,将会在编译时显示提示信息,这些过时方法也是可以正常使用的,只是被提示标记而已,与javadoc里的@deprecated注解的功能相同,但 javadoc @deprecated 可以支持参数。
3、@SuppressWarnings:作用是压制警告;可选值有以下几种(写哪种值就代表压制哪种类型的警告):
deprecation:使用了过时的类或方法时的警告(即被@Deprecated标记的类或方法)
unchecked:执行了未检查的转换时的警告(如使用集合时没有用泛型 (Generics) 来指定集合保存的类型)
fallthrough:当 switch 程序块直接通往下一种情况而没有 break 时的警告
path:在类路径、源文件路径等中有不存在的路径时的警告
serial:当在可序列化的类上缺少serialVersionUID 定义时的警告
finally :任何 finally 子句不能正常完成时的警告
rawtypes:泛型类型未指明
unused 引用定义了,但是没有被使用
all:关于以上所有情况的警告
在这里插入图片描述
在这里插入图片描述

三、元注解

元注解的作用就是负责注解其他注解,Java定义了4个标准的meta-annotation类型他们被用来提供对其他annotation类型作说明,
这些类型和它们所支持的类在java.langannotation包中可以找到(@Target,@Retention,@Documented,@Inherited )。
@Target:用于描述注解的使用范围(即:@Target元注解用来设置注解可以用在什么地方),经常使用最主要的就三个:TYPE、METHOD、FIELD

package java.lang.annotation;

/**
 * The constants of this enumerated type provide a simple classification of the
 * syntactic locations where annotations may appear in a Java program. These
 * constants are used in {@link Target java.lang.annotation.Target}
 * meta-annotations to specify where it is legal to write annotations of a
 * given type.
 *
 * <p>The syntactic locations where annotations may appear are split into
 * <em>declaration contexts</em> , where annotations apply to declarations, and
 * <em>type contexts</em> , where annotations apply to types used in
 * declarations and expressions.
 *
 * <p>The constants {@link #ANNOTATION_TYPE} , {@link #CONSTRUCTOR} , {@link
 * #FIELD} , {@link #LOCAL_VARIABLE} , {@link #METHOD} , {@link #PACKAGE} ,
 * {@link #PARAMETER} , {@link #TYPE} , and {@link #TYPE_PARAMETER} correspond
 * to the declaration contexts in JLS 9.6.4.1.
 *
 * <p>For example, an annotation whose type is meta-annotated with
 * {@code @Target(ElementType.FIELD)} may only be written as a modifier for a
 * field declaration.
 *
 * <p>The constant {@link #TYPE_USE} corresponds to the 15 type contexts in JLS
 * 4.11, as well as to two declaration contexts: type declarations (including
 * annotation type declarations) and type parameter declarations.
 *
 * <p>For example, an annotation whose type is meta-annotated with
 * {@code @Target(ElementType.TYPE_USE)} may be written on the type of a field
 * (or within the type of the field, if it is a nested, parameterized, or array
 * type), and may also appear as a modifier for, say, a class declaration.
 *
 * <p>The {@code TYPE_USE} constant includes type declarations and type
 * parameter declarations as a convenience for designers of type checkers which
 * give semantics to annotation types. For example, if the annotation type
 * {@code NonNull} is meta-annotated with
 * {@code @Target(ElementType.TYPE_USE)}, then {@code @NonNull}
 * {@code class C {...}} could be treated by a type checker as indicating that
 * all variables of class {@code C} are non-null, while still allowing
 * variables of other classes to be non-null or not non-null based on whether
 * {@code @NonNull} appears at the variable's declaration.
 *
 * @author  Joshua Bloch
 * @since 1.5
 * @jls 9.6.4.1 @Target
 * @jls 4.1 The Kinds of Types and Values
 */
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration 类, 接口 (包括注释类型), 或 枚举 声明*/
    TYPE,

    /** Field declaration (includes enum constants) 字段声明(包括枚举常量)*/
    FIELD,

    /** Method declaration 方法声明(Method declaration)*/
    METHOD,

    /** Formal parameter declaration 正式的参数声明*/
    PARAMETER,

    /** Constructor declaration 构造函数声明*/
    CONSTRUCTOR,

    /** Local variable declaration 局部变量声明*/
    LOCAL_VARIABLE,

    /** Annotation type declaration 注解类型声明*/
    ANNOTATION_TYPE,

    /** Package declaration 包声明*/
    PACKAGE,

    /**
     * Type parameter declaration 类型参数声明
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type 使用的类型
     *
     * @since 1.8
     */
    TYPE_USE
}

@Retention:表示需要在什么级别保存该注解信息,用于描述注解的生命周期 (可选值:SOURCE <CLASS < RUNTIME)
在这里插入图片描述
@Documented:说明该注解将被包含在javadoc中(即注解是否被抽取到api文档中,使用 javadoc 类文件名称 命令生成文档时将该注解是否保留在文档中)
@Inherited:说明子类可以继承父类中使用的被@Inherited注解标记的注解(比如:A类是B类的父类,如果在A类上使用被@Inherited元注解声明的注解,那么B类也会继承该注解,会自动加上该注解)

四、自定义注解

1、格式:
元注解
public @interface 注解名称{
注解属性列表(即接口中的抽象方法)
}

package com.database.pool.testpool.annotation;

import java.lang.annotation.*;

/**
 * 测试注解1
 */
@Target(value = ElementType.TYPE)  //元注解定义当前注解可使用范围
@Retention(value = RetentionPolicy.RUNTIME)  //元注解定义当前注解生命周期
@Inherited  //元注解定义子类可以继承父类中使用的该注解
public @interface Test1Annotation {
    //属性
    String value();
}

2、本质 :注解本质上就是一个接口,该接口默认继承Annotation接口
public interface Test1Annotation extends java.lang.annotation.Annotation {}
在这里插入图片描述
3、注解属性说明 : 接口中的抽象方法
a、属性(抽象方法)返回值要求,只能是以下几种类型:

  • 八大基本数据类型
  • String
  • 枚举
  • 注解
  • 以上四种类型的数组

b、使用注解时需要给属性赋值要求如下:

  • 定义了属性使用时就必须给属性赋值(格式:@注解名(属性名1=属性值1,属性名2=属性值2))。
  • 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行该属性的赋值会自动使用默认值。
  • 使用注解时如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可也就是说注解只有一个value名称的属性或注解有多个属性,但这些属性都有默认值,所以使用时只需要对value属性赋值的话也可以直接写值。
  • 数组属性赋值时,值使用{}包裹属性值,如果数组中只有一个值,则{}省略,直接写值。

建议注解如果只有一个属性,那么将该属性名定义为value。

示例:
自定义注解:

package com.database.pool.testpool.annotation;

import com.database.pool.testpool.User;

import java.lang.annotation.*;

/**
 * 测试注解1
 */
@Target(value = ElementType.TYPE)  //元注解定义当前注解可使用范围
@Retention(value = RetentionPolicy.RUNTIME)  //元注解定义当前注解生命周期
@Inherited  //元注解定义子类可以继承父类中的该注解,子类可以继承父类使用的注解
public @interface Test1Annotation {

    /**
     * 属性(抽象方法)定义
     * @return
     */
    int paramInt();

    //default 标记属性默认值,使用注解时该属性如果不做更改使用默认值时可以不设置该属性的值
    String paramStr() default "c";

    //返回类型是另一个注解类型
    Test1Annotation2 paramAnn();

    //返回类型是枚举
    User paramUser();

    String[] paramStrArr();


    //value名称的属性,在使用注解时如果只有value属性设置值则可以省略属性名value直接写值
    String value();
}

测试注解2:

package com.database.pool.testpool.annotation;

import java.lang.annotation.*;

/**
 * 测试注解2,用于给测试注解1的属性设置返回值为注解类型
 */
@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface Test1Annotation2 {
}

枚举:

package com.database.pool.testpool;

/**
 * 定义枚举,用于设置测试注解1的属性返回值为枚举类型
 */
public enum User {

    U1,U2;

}

使用注解:

package com.database.pool.testpool;

import com.database.pool.testpool.annotation.Test1Annotation;
import com.database.pool.testpool.annotation.Test1Annotation2;

/**
 * 测试注解1使用类
 */
@Test1Annotation(paramInt = 1,paramAnn = @Test1Annotation2,paramStrArr = {"a","b"},paramUser = User.U1,value = "x")
public class TestAnn {
}

解析注解:

package com.database.pool.testpool;

import com.database.pool.testpool.annotation.Test1Annotation;

/**
 * 反射解析自定义注解---测试注解1
 */
public class Test {

    public static void main(String[] args) {
        //获取Class对象
        Class<TestAnn> aClass = TestAnn.class;
        //获取类级别的Test1Annotation类型的注解,实际上返回值是一个实现了Test1Annotation注解接口的类的对象,里面有获取各个属性的值的方法
        Test1Annotation annotation = aClass.getAnnotation(Test1Annotation.class);
        //拿到注解信息后就可以根据注解信息做各种操作
        int i = annotation.paramInt();
        System.out.println("paramInt:"+i);
        String s = annotation.paramStr();
        System.out.println("paramStr:"+s);
        String value = annotation.value();
        System.out.println("value:"+value);
    }

}

总结:
1、程序开发中大部分时候是使用注解,而不是自定义注解
2、注解给谁用 ? 编译器(编译器识别注解),给解析程序用(解析程序通过解析注解实现自定义功能)
3、注解不是程序的一部分(相当于是给程序做了一个标记,然后通过反射机制实现注解功能,对程序原有功能做增强等)
Java反射
Java泛型

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

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

相关文章

三、虚拟机的迁移和删除

虚拟机的本质就是文件(放在文件夹的)。因此虚拟机的迁移很方便&#xff0c;可以把安装好的虚拟系统这个文件夹整体拷贝或者剪切到另外的位置使用。删除也很简单&#xff0c;使用vmware进行移除&#xff0c;再点菜单->从磁盘删除即可&#xff0c;或者手动删除虚拟系统对应的文…

【C++入门系列】——类和对象中篇

​作者主页 &#x1f4da;lovewold少个r博客主页 ⚠️本文重点&#xff1a;C构造函数、构析函数、运算符重载等详解 &#x1f604;前篇文章链接&#xff1a;【类和对象上】http://t.csdnimg.cn/bTQ0Y 目录 前言 类的默认成员函数 构造函数 默认构造 全缺省和无参默认构造 …

vue3+vite引入图片不能再用require,要使用new Url(完整方法步骤)

由于vite里面没有require(), 所以需要封装个工具 export const getAssetURL (image) > {// 参数一: 相对路径// 参数二: 当前路径的URLreturn new URL(../assets/img/${image}, import.meta.url).href }

【Proteus仿真】【Arduino单片机】直流电机和步进电机

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用蜂鸣器、按键、直流电机、步进电机、ULN2003、L293D等。 主要功能&#xff1a; 系统运行后&#xff0c;K3键启动运行&#xff0c;K1和K2键控制…

飞驰云联:让企业文件同步变得更简单

在如今这个高度信息化的时代&#xff0c;企业的文件同步需求日益增长&#xff0c;如何高效、安全地实现文件同步已成为企业亟待解决的问题。飞驰云联的文件同步系统作为一款全新的解决方案&#xff0c;能够满足各种企业对于文件同步的需求&#xff0c;提高工作效率&#xff0c;…

JXLS2同一个sheet多个表格循环覆盖下面表格数据问题

excel 模版&#xff1a; 输出结果 java 代码片段&#xff1a; private static void test01(String name) throws IOException {try (InputStream in new FileInputStream(new File(String.format(gen, name)));OutputStream out new FileOutputStream(new File(String.for…

UnoCSS快速入门

UnoCSS快速入门 UnoCSS一、UnoCSS简介二、UnoCSS解决问题三、UnoCSS实践四、好文推荐 UnoCSS 一、UnoCSS简介 UnoCSS 是一个即时、按需的原子级 CSS 引擎。它专注于提供轻量化、高性能的 CSS 解决方案。“Instant On-demand” 表示 UnoCSS 的加载和渲染速度非常快&#xff0c;…

V8 引擎中的垃圾收集器

V8 引擎中的垃圾收集器 垃圾收集是跟踪活动对象的过程&#xff0c;同时销毁堆内存中未引用的对象&#xff0c;为将来创建的新对象腾出空间。本文将讨论V8 引擎的垃圾收集器&#xff0c;V8 引擎是由 Google 用 C 编写开发的开源、高性能 JavaScript 和 WebAssembly 引擎。 V8 引…

three.js第一课

官网 1.创建场景 2.创建几何体 3.创建材质 4.创建网格模型 5.将几何体、材质加入网格模型&#xff0c;设置网格模型的位置&#xff0c;将网格模型加入场景中 6.创建相机&#xff0c;构造函数中设置角度、最后面视椎体的长宽比&#xff0c;相机离视椎体近端面的距离、视椎体的远…

算法训练营第二天 | 977.有序数组的平方、209.长度最小的子数组、 59.螺旋矩阵II

问题&#xff08; 一 &#xff09; 问题描述&#xff1a; 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组&#xff0c;要求也按 非递减顺序 排序 题目链接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱…

并发编程- 线程池ForkJoinPool工作原理分析(实践)

数据结构加油站&#xff1a; Comparison Sorting Visualization 并发设计模式 单线程归并排序 public class MergeSort {private final int[] arrayToSort; //要排序的数组private final int threshold; //拆分的阈值&#xff0c;低于此阈值就不再进行拆分public MergeSort…

重学JDK8新特性之Stream

集合处理数据的弊端 当我们在需要对集合中的元素进行操作的时候&#xff0c;除了必需的添加&#xff0c;删除&#xff0c;获取外&#xff0c;最典型的操作就是 集合遍历 public static void main(String[] args) {// 定义一个List集合List<String> list Arrays.asList…

流程引擎-自定义函数的应用

背景&#xff1a; 某些业务需求比较特殊&#xff0c;需要在表单中校验或实现一些功能&#xff0c;泛微流程表单配置时实现的方式多种多样&#xff1a;JS脚本、SQL语句、公式以及其他一些标准化拖拽功能&#xff0c;本次给大家分享一下流程表单中的公式实现的一些需求场景。泛微…

动态组件<component>

用法&#xff1a; <template><div><Navbar></Navbar><Home v-if"componentName 首页"></Home><List v-else-if"componentName 列表"></List><Center v-else-if"componentName 我的">…

公众号爆文写作怎么做?或许这些领域才适合你!

最近分享了很多爆款案例&#xff0c;看了的人都在跟进&#xff0c;有些人做得很出色&#xff0c;持续出爆款&#xff0c;但还是有人遇到了瓶颈&#xff0c;阅读量停滞不前。 其实&#xff0c;能否成功与个人能力、经验、环境以及一丢丢的运气有关。 但是&#xff0c;公众号不止…

PTL电子标签助力仓储行业转型升级提升拣货效率降低误差率

在智能物流、智能工厂和智能零售等行业的快速发展中&#xff0c;电子货位标签、物流智能设备和专业智能穿戴产品的应用变得越来越重要。这些技术的引入为仓储行业带来了巨大的变革和提升。作为一家致力于电子货位标签、物流智能设备和专业智能穿戴产品的开发和市场推广的公司&a…

windows10下SQL Prompt安装和注册

文章目录 windows10下SQL Prompt安装下载安装程序安装关闭联网注册机使用测试卸载 windows10下SQL Prompt安装 下载安装程序 官网 下载后 安装 双击打开界面 关闭联网 激活失效&#xff1a; 方法1&#xff1a;在本地hosts加入以下代码&#xff1a; 127.0.0.1 licensin…

Fabric.js 自定义控件

本文简介 带尬猴&#xff0c;我是德育处主任 虽然 Fabric.js 提供的基础功能已经很丰富了&#xff0c;但有时难免需要定制一些需求。比如本文要讲的 『自定义控件』。掌握创建自定义控件这个功能&#xff0c;能够创建更加精美和实用的图形应用程序&#xff0c;提高用户体验和用…

pycharm远程连接Linux服务器

文章目录 一&#xff1a;说明二&#xff1a;系统三&#xff1a;实现远程连接方式一&#xff1a; 直接连接服务器不使用服务器的虚拟环境步骤一&#xff1a;找到配置服务器的地方步骤二&#xff1a;进行连接配置步骤三&#xff1a;进行项目文件映射操作步骤四&#xff1a;让文件…

【JavaSE专栏53】Java集合类HashMap详解

Java集合类HashMap详解 摘要引言1. HashMap简介&#xff1a;掌握什么是HashMap&#xff1f;&#x1f9d0;2. HashMap的操作技巧&#xff1a;从基础到高级&#x1f680;2.1 添加键值对&#xff1a;put(K key, V value) &#x1f4e5;2.2 获取值&#xff1a;get(Object key) &…