Java 基础 - 注解

2023-11-09

目录

注解基础

Java内置注解

元注解

注解与反射接口

自定义注解


注解基础

注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包、类、接口、字段、方法参数、局部变量等进行注解。它主要的作用有以下四方面:

  • 生成文档,通过代码里标识的元数据生成javadoc文档。
  • 编译检查,通过代码里标识的元数据让编译器在编译期间进行检查验证。
  • 编译时动态处理,编译时通过代码里标识的元数据动态处理,例如动态生成代码。
  • 运行时动态处理,运行时通过代码里标识的元数据动态处理,例如使用反射注入实例。

常见分类:

  • Java自带的标准注解,包括@Override@Deprecated@SuppressWarnings,分别用于标明重写某个方法、标明某个类或方法过时、标明要忽略的警告,用这些注解标明后编译器就会进行检查。
  • 元注解,元注解是用于定义注解的注解,包括@Retention@Target@Inherited@Documented@Retention用于标明注解被保留的阶段,@Target用于标明注解使用的范围,@Inherited用于标明注解可继承,@Documented用于标明是否生成javadoc文档。
  • 自定义注解,可以根据自己的需求定义注解,并可用元注解对自定义注解进行注解。

Java内置注解

  • @Override:表示当前的方法定义将覆盖父类中的方法
  • @Deprecated:表示代码被弃用,如果使用了被@Deprecated注解的代码则编译器将发出警告
  • @SuppressWarnings:表示关闭编译器警告信息

@Override

注解类型的定义:

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

从它的定义我们可以看到,这个注解可以被用来修饰方法,并且它只在编译时有效,在编译后的class文件中便不再存在。这个注解的作用我们大家都不陌生,那就是告诉编译器被修饰的方法是重写的父类的中的相同签名的方法,编译器会对此做出检查,若发现父类中不存在这个方法或是存在的方法签名不同,则会报错。

@Deprecated

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

从它的定义我们可以知道,它会被文档化,能够保留到运行时,能够修饰构造方法、属性、局部变量、方法、包、参数、类型。这个注解的作用是告诉编译器被修饰的程序元素已被“废弃”,不再建议用户使用。

@SuppressWarnings

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

它能够修饰的程序元素包括类型、属性、方法、参数、构造器、局部变量,只能存活在源码时,取值为String[]。它的作用是告诉编译器忽略指定的警告信息,它可以取的值如下所示:

参数 作用 原描述
all 抑制所有警告 to suppress all warnings
boxing 抑制装箱、拆箱操作时候的警告 to suppress warnings relative to boxing/unboxing operations
cast 抑制映射相关的警告 to suppress warnings relative to cast operations
dep-ann 抑制启用注释的警告 to suppress warnings relative to deprecated annotation
deprecation 抑制过期方法警告 to suppress warnings relative to deprecation
fallthrough 抑制确在switch中缺失breaks的警告 to suppress warnings relative to missing breaks in switch statements
finally 抑制finally模块没有返回的警告 to suppress warnings relative to finally block that don’t return
hiding 抑制与隐藏变数的区域变数相关的警告 to suppress warnings relative to locals that hide variable()
incomplete-switch 忽略没有完整的switch语句 to suppress warnings relative to missing entries in a switch statement (enum case)
nls 忽略非nls格式的字符 to suppress warnings relative to non-nls string literals
null 忽略对null的操作 to suppress warnings relative to null analysis
rawtype 使用generics时忽略没有指定相应的类型 to suppress warnings relative to un-specific types when using
restriction 抑制与使用不建议或禁止参照相关的警告 to suppress warnings relative to usage of discouraged or
serial 忽略在serializable类中没有声明serialVersionUID变量 to suppress warnings relative to missing serialVersionUID field for a serializable class
static-access 抑制不正确的静态访问方式警告 to suppress warnings relative to incorrect static access
synthetic-access 抑制子类没有按最优方法访问内部类的警告 to suppress warnings relative to unoptimized access from inner classes
unchecked 抑制没有进行类型检查操作的警告 to suppress warnings relative to unchecked operations
unqualified-field-access 抑制没有权限访问的域的警告 to suppress warnings relative to field access unqualified
unused 抑制没被使用过的代码的警告 to suppress warnings relative to unused code

元注解

上述内置注解的定义中使用了一些元注解(注解类型进行注解的注解类),在JDK 1.5中提供了4个标准的元注解:@Target@Retention@Documented@Inherited, 在JDK 1.8中提供了两个元注解 @Repeatable@Native

@Target

Target注解用来说明那些被它所注解的注解类可修饰的对象范围:注解可以用于修饰 packages、types(类、接口、枚举、注解类)、类成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数),在定义注解类时使用了@Target 能够更加清晰的知道它能够被用来修饰哪些对象,它的取值范围定义在ElementType 枚举中。

public enum ElementType {
 
    TYPE, // 类、接口、枚举类
 
    FIELD, // 成员变量(包括:枚举常量)
 
    METHOD, // 成员方法
 
    PARAMETER, // 方法参数
 
    CONSTRUCTOR, // 构造方法
 
    LOCAL_VARIABLE, // 局部变量
 
    ANNOTATION_TYPE, // 注解类
 
    PACKAGE, // 可用于修饰:包
 
    TYPE_PARAMETER, // 类型参数,JDK 1.8 新增
 
    TYPE_USE // 使用类型的任何地方,JDK 1.8 新增
 
}

 @Retention & @RetentionTarget

 Reteniton注解用来限定那些被它所注解的注解类在注解到其他类上以后,可被保留到何时,一共有三种策略,定义在RetentionPolicy枚举中。

public enum RetentionPolicy {
 
    SOURCE,    // 源文件保留
    CLASS,       // 编译期保留,默认值
    RUNTIME   // 运行期保留,可通过反射去获取注解信息
}

 @Documented

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

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
 
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface TestDocAnnotation {
 
	public String value() default "default";
}

@Inherited

Inherited注解的作用:被它修饰的Annotation将具有继承性。如果某个类使用了被@Inherited修饰的Annotation,则其子类将自动具有该注解。

定义@Inherited注解:

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface TestInherited {
    String [] values();
    int number();
}

使用这个注解

@TestInherited(values = {"value"}, number = 10)
public class Person {
}

class Student extends Person{
	@Test
    public void test(){
        Class clazz = Student.class;
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation.toString());
        }
    }
}

即使Student类没有显示地被注解@TestInherited,但是它的父类Person被注解,而且@TestInherited@Inherited注解,因此Student类自动有了该注解。

@Native (Java8)

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

@Repeatable (Java8)

创建复注解Authority时,加上@Repeatable,指向存储注解Authorities,在使用时候,直接可以重复使用Authority注解。

注解与反射接口

定义注解后,如何获取注解中的内容呢?反射包java.lang.reflect下的AnnotatedElement接口提供这些方法。这里注意:只有注解被定义为RUNTIME后,该注解才能是运行时可见,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取。

AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的方法来访问Annotation信息。我们看下具体的先关接口

  • boolean isAnnotationPresent(Class<?extends Annotation> annotationClass)

判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false。注意:此方法会忽略注解对应的注解容器。

  • <T extends Annotation> T getAnnotation(Class<T> annotationClass)

返回该程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。

  • Annotation[] getAnnotations()

返回该程序元素上存在的所有注解,若没有注解,返回长度为0的数组。

  • <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)

返回该程序元素上存在的、指定类型的注解数组。没有注解对应类型的注解时,返回长度为0的数组。该方法的调用者可以随意修改返回的数组,而不会对其他调用者返回的数组产生任何影响。getAnnotationsByType方法与 getAnnotation的区别在于,getAnnotationsByType会检测注解对应的重复注解容器。若程序元素为类,当前类上找不到注解,且该注解为可继承的,则会去父类上检测对应的注解。

  • <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass)

返回直接存在于此元素上的所有注解。与此接口中的其他方法不同,该方法将忽略继承的注释。如果没有注释直接存在于此元素上,则返回null

  • <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass)

返回直接存在于此元素上的所有注解。与此接口中的其他方法不同,该方法将忽略继承的注释

  • Annotation[] getDeclaredAnnotations()

返回直接存在于此元素上的所有注解及注解对应的重复注解容器。与此接口中的其他方法不同,该方法将忽略继承的注解。如果没有注释直接存在于此元素上,则返回长度为零的一个数组。该方法的调用者可以随意修改返回的数组,而不会对其他调用者返回的数组产生任何影响。

自定义注解

定义自己的注解

package com.liarboy.java.annotation;

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

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyMethodAnnotation {

    public String name() default "";

    public String sex() default "";

}

使用注解

package com.liarboy.java.annotation;

import java.io.FileNotFoundException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class TestMethod {

    @Override
    @MyMethodAnnotation (name= "liarboy", sex= "boy")
    public String toString() {
        return "Override toString method";
    }

    @Deprecated
    @MyMethodAnnotation (name= "liarboy static method", sex= "boyold static method")
    public static void oldMethod() {
        System.out.println("old method, don't use it.");
    }

    @SuppressWarnings({"unchecked", "deprecation"})
    @MyMethodAnnotation (name= "test method", sex= "suppress warning static method")
    public static void genericsTest() throws FileNotFoundException {
        List l = new ArrayList();
        l.add("abc");
        oldMethod();
    }
}

用反射接口获取注解信息

public static void main(String[] args) {
    try {
        // 获取所有methods
        Method[] methods = TestMethodAnnotation.class.getClassLoader()
                .loadClass(("com.pdai.java.annotation.TestMethodAnnotation"))
                .getMethods();

        // 遍历
        for (Method method : methods) {
            // 方法上是否有MyMethodAnnotation注解
            if (method.isAnnotationPresent(MyMethodAnnotation.class)) {
                try {
                    // 获取并遍历方法上的所有注解
                    for (Annotation anno : method.getDeclaredAnnotations()) {
                        System.out.println("Annotation in Method '"
                                + method + "' : " + anno);
                    }

                    // 获取MyMethodAnnotation对象信息
                    MyMethodAnnotation methodAnno = method
                            .getAnnotation(MyMethodAnnotation.class);

                    System.out.println(methodAnno.title());

                } catch (Throwable ex) {
                    ex.printStackTrace();
                }
            }
        }
    } catch (SecurityException | ClassNotFoundException e) {
        e.printStackTrace();
    }
}


 激动的心,颤抖的手

 借用客官你们发财的小手,给个鼓励吧

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 基础 - 注解 的相关文章

  • 使用 BlobOutputStream 在 Azure 中上传 blob

    我正在尝试直接从流上传 blob 因为我不知道我决定尝试的流的长度这个答案 https stackoverflow com a 24621538 3695939 这不起作用 即使它从流中读取并且不会抛出任何异常 内容也不会上传到我的容器 我
  • 相当于 java PBKDF2WithHmacSHA1 的 Python

    我的任务是构建一个 API 的使用者 该 API 需要带有 UNIX 时间种子值的加密令牌 我看到的示例是使用我不熟悉的 Java 实现的 在阅读文档和其他堆栈文章后一直无法找到解决方案 使用javax crypto SecretKey j
  • Java selenium - 如何在 TimeoutException 之后正确刷新网页?

    ChromeOptions options new ChromeOptions options addExtensions new File extension 6 2 5 0 crx ZenMate options addExtensio
  • Java 7u51/7u55 带星号的清单变量

    我正在部署一个小程序 其中包含清单中的下一个变量 Manifest Version 2 0 Ant Version Apache Ant 1 8 2 Trusted Library true Permissions all permissi
  • Java中如何对对象数组进行排序?

    我的数组不包含任何字符串 但它包含对象引用 每个对象引用都通过 toString 方法返回名称 id 作者和发布者 public String toString return name n id n author n publisher n
  • 如何访问EmbeddedSolrServer实例的管理界面?

    在我的网络应用程序中 我正在运行org apache solr client solrj embedded EmbeddedSolrServer出于调试目的 我想访问管理界面 这就是我实例化服务器的方式 new EmbeddedSolrSe
  • 如何对 jar 文件资源使用 File.separator?

    我正在尝试读取位于 jar 文件中的属性文件 我想使用 File separator 因为应用程序将在多个平台上运行 我正在构建路径如下 jarFilePath jar file jarFile getAbsolutePath jarPro
  • 参考接口创建对象

    引用变量可以声明为类类型或接口类型 如果变量声明为接口类型 则它可以引用实现该接口的任何类的任何对象 根据上面的说法我做了一个理解上的代码 正如上面所说声明为接口类型 它可以引用实现该接口的任何类的任何对象 但在我的代码中显示display
  • 使用 POJO 仅更新 JOOQ 记录中已更改的字段

    我想使用 POJO 作为源来更新 JOOQ 记录中已更改的字段 Record from Object http www jooq org javadoc 3 8 x org jooq Record html from java lang O
  • grails 中的 log4j:如何登录文件?

    我的 grails config groovy 中有这个 log4j 配置 log4j error org codehaus groovy grails web servlet controllers org codehaus groovy
  • Java MYSQL/JDBC 查询从缓存的连接返回过时的数据

    我一直在 Stackoverflow 中寻找答案 但似乎找不到不涉及 Hibernate 或其他数据库包装器的答案 我直接通过 Tomcat 6 Java EE 应用程序中的 MYSQL 5 18 JDBC 驱动程序使用 JDBC 我正在缓
  • 如何根据从 jtextfield 和组合框接收的值将数据行添加到 Jtable

    我有一个JFrame表格有JTextFields JCombobox等等 我能够将这些值接收到变量 现在我想将接收到的数据添加到JTable当用户单击 添加 或类似的操作时在新行中 我创造了JTable使用 net beans 的问题是将这
  • 为什么 CompletableFuture 的 thenAccept() 不在主线程上运行

    我在 CompletableFuture 的 SupplyAsync 中处理长时间运行的操作 并将结果放入 thenAccept 中 有时 thenAccept 在主线程上执行 但有时它在工作线程上运行 但我只想在主线程上运行 thenAc
  • Java 中的连接路径

    In Python我可以连接两条路径os path join os path join foo bar gt foo bar 我正在尝试在 Java 中实现相同的目标 而不用担心是否OS is Unix Solaris or Windows
  • 使用 Retrofit 获取原始 HTTP 响应

    我想从我的 API REST 获取原始 http 响应 我尝试过这个界面 POST login FormUrlEncoded Call
  • Java 执行器和长寿命线程

    我继承了一些使用 Executors newFixedThreadPool 4 的代码运行 4 个长寿命线程来完成应用程序的所有工作 这是推荐的吗 我读过Java 并发实践 https rads stackoverflow com amzn
  • Spring Data MongoDB 和批量更新

    我正在使用 Spring Data MongoDB 并且想要执行批量更新 就像此处描述的那样 http docs mongodb org manual reference method Bulk find update Bulk find
  • 在 Spark MLlib 上使用 Java 中的 Breeze

    在尝试从Java使用MLlib时 使用微风矩阵运算的正确方法是什么 例如scala 中的乘法很简单 matrix vector 相应的功能在Java中是如何表达的 有一些方法 例如 colon times 可以通过正确的方式调用 breez
  • 如何在 tomcat 上部署 Java Web 应用程序 (.war)?

    我有一个 warJava Web 应用程序的文件 现在我想将它上传到我的 ftp 服务器 以便我可以执行它 我应该执行哪些步骤来运行它 webapp的上下文路径是 mywebapp Edit 实际上 我的 ftp 服务器名称是ftp bil
  • Selenium Webdriver - 单击多个下拉菜单时出现陈旧元素异常,而 HTML DOM 不会更改

    我尝试自动化一个场景 其中条件是我必须从下拉列表中选择一个选项 然后它旁边有另一个下拉列表 我必须单击下一个下拉列表中的一个选项才能启用按钮 我尝试使用代码 但它仅单击第一个选项 并显示错误为过时的元素引用 元素未附加到页面文档 请帮忙 如

随机推荐

  • 2023春节祝福系列第一弹(上)(放飞祈福孔明灯,祝福大家身体健康)(附完整源代码及资源免费下载)

    2023春节祝福系列第一弹 上 放飞祈福孔明灯 祝福大家身体健康 附完整源代码及资源免费下载 目录 一 前言 二 一片星光闪烁的旋转星空 1 效果展示 2 相关源代码 3 语法解释 3 1 线性渐变 linear gradient 3 2
  • Java异常知识点总结

    Java异常知识点总结 1 异常处理机制主要回答了三个问题 What Where Why What 异常类型回答了什么被抛出 Where 异常堆栈跟踪回答了在哪抛出 Why 异常信息回答了为什么被抛出 2 Java异常体系 RuntimeE
  • Python的Object基类__repr__方法

    Python的Object基类 repr 方法 Python基类的內建方法 repr 是执行一个官方的 或者正式的 代表一个对象的字符串 也就是说可以将字符串转换成一个Python对象 如果可能的话 最好是有效的表达式字符串 如果不可能的话
  • Visual Studio 2017 如何更改缓存以及组件的路径,以保证VS2017正常启动

    当安装完Visual Studio 2017时 发现安装过程中设置的缓存路径或组件存放路径不合理 但一旦修改 会导致Visual Studio 2017出现项目加载失败等问题 修改方法是通过 regedit命令打开windows注册表 然后
  • 财务系统软件c语言,用vc++6.0编写一个简单的财务应用程序来计算职工所得的实际工资...

    满意答案 xfitijnf 2014 09 30 采纳率 51 等级 12 已帮助 32118人 又写了一个简单的 c语言 另外 我和一楼不是一个人 123456789101112131415161718192021222324252627
  • Redis为服务器设置密码

    以下以Windows版本为例 在 redis windows service conf 文件 设置 requirepass foobared requirepass 123456 masterauth
  • AD常用使用快捷键和技巧

    PCB布线常使用 ctrl m 测量长度 ctrl C 取消显示测量长度 Q 单位切换 shift ctrl r 取消显示标注 shift S 显示层切换 ctrl 右击 高亮显示一条线 ctrl D PCB 2D显示设置 层 透明度 A
  • OpenCV:imwrite函数保存图片

    imwrite函数功能 用于将图像保存到指定的文件 可以为各种格式的图像 函数原型 bool cv imwrite const String filename InputArray img const std vector
  • js实现input的赋值

    input框赋值 如下所示 是一个文本框的html代码 实际开发中 要涉及到将数据库中的数据取出然后放入input框中
  • UML 用例图、顺序图、状态图、类图、包图、协作图、流程图

    面向对象的问题的处理的关键是建模问题 建模可以把在复杂世界的许多重要的细节给抽象出 许多建模工具封装了UML 也就是Unified Modeling Language 这篇课程的目的是展示出UML的精彩之处 UML中有九种建模的图标 即 用
  • vue事件对象、冒泡、阻止默认行为

    事件对象
  • 【满分】【华为OD机试真题2023 JAVA&JS】任务混部

    华为OD机试真题 2023年度机试题库全覆盖 刷题指南点这里 任务混部 知识点差分 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 公司创新实验室正在研究如何最小化资源成本 最大化资源利用率 请你设计算法帮他们解决一个任务混
  • sql-labs注入1-10关

    sql labs注入第1 10关 Less 1 输入 id 1登录页面正常 Order by对前面的数据进行排序 这里有三列数据 我们就只能用order by 3 超过3就会报错 order by 4 的结果显示结果超出 爆数据库名 id
  • SpringBoot+MyBatis搭建迷你小程序

    本项目如下 maven的安装目录在哪 setting文件放在哪 仓库在哪 分别为G Program Files x86 apache maven 3 5 4 conf 与G Program Files x86 apache maven 3
  • 【高等代数】行列式的定义和性质

    文章目录 逆序数 逆序数的定义 逆序数的一个重要性质 行列式的定义 行列式的性质 逆序数 逆序数的定义 一个排列中的某两个数字 如果前面的数大于后面的数 那么它们就是一个逆序 一个排列中逆序的总数就称为这个排列的逆序数 逆序数用 j 1
  • JAVA的安装与卸载

    1 java的卸载 1 删除java的安装目录 2 删除系统环境变量里的JAVA HOME和Path里面的bin目录和jre bin目录 3 cmd输入java version 查看是否删除取消 2 java的安装 1 百度搜索jdk1 8
  • 【算法题】螺旋矩阵III (求解n阶蛇形矩阵)

    一 问题的提出 n阶蛇形矩阵的特点是按照图1所示的方式排列元素 n阶蛇形矩阵是指矩阵的大小为n n 其中n为正整数 题目背景 一个 n 行 n 列的螺旋矩阵可由如图1所示的方法生成 观察图片 找出填数规律 填数规则为从 1 开始填到 n n
  • Zinx框架学习 - 构建最基础的Server

    Zinx V0 1 构建最基础的Server Zinx的框架结构 整体思路 客户端发送请求到服务器端 服务端会有一个Goroutine专门处理listenner和监听这个过程 然后有客户端连接过来之后会启动一个客户端处理Goroutine
  • Mayor‘s posters (线段树+离散化)

    题目链接 Mayor s posters 思路 由于看到l r的值最大可达到1e7 这时候如果强行build 那么大概率会出错 看到n的值只有1e4 这时候我们应该想到用离散化去解决这个问题 而且 这里还有一个坑点 假如所给区间为 1 4
  • Java 基础 - 注解

    目录 注解基础 Java内置注解 元注解 注解与反射接口 自定义注解 注解基础 注解是JDK1 5版本开始引入的一个特性 用于对代码进行说明 可以对包 类 接口 字段 方法参数 局部变量等进行注解 它主要的作用有以下四方面 生成文档 通过代