excel批注不显示批注框_批注和批注处理器入门指南[解释]

article/2025/7/18 16:26:44

excel批注不显示批注框

在Java中,大多数情况下,批注和批注处理器都被一团谜团包围。 他们看起来像是为“专家”保留的主题。 最重要的是,我相信他们周围也有一些FUD。

这篇文章旨在以最中立的方式深入探讨该主题。 这样,每个人都可以根据事实做出明智的决定,而不必听取充满误解或隐藏议程的人们的意见。

自Java版本5(代号为Tiger)于2004年发布以来,便可以使用注释。

在Java计算机编程语言中,注释是一种语法元数据,可以添加到Java源代码中。 类,方法,变量,参数和Java包可能会带有注释。
—维基百科
https://zh.wikipedia.org/wiki/Java_annotation

最简单的注释如下所示:

@MyAnnotation public class Foo  {}

由于缺少注释,以前的Java版本必须以倾斜的方式使用某些功能。

更换标记器接口

自Java诞生以来,就需要标记一个类或层次结构
类。 在Java 5之前,这是通过没有方法的接口完成的。 Serializable和可Cloneable是此类接口的两个示例。

这种接口显然不同于其他接口:它们在自己和实现类之间未定义任何协定。 因此,他们赢得了标记器接口的名称。

Java新手通常会问与该方法有关的问题。 这样做的原因是因为这是一个把戏。 注释消除了对该技巧的需要,并保留了接口的协定角色。

public class Foo implements MarkerInterface  {} // 1@MyAnnotation
public class Foo  {}         // 2                   
  1. 标记界面
  2. 等同于标记界面的注释

更好的元数据管理

弃用是将API标记为过时的过程。 这样,用户可以获知有关更改的信息,可以决定停止使用该API,并且可以在以后的版本中以较小的影响删除该API。 在Java 5之前,JavaDoc中设置了弃用:

/*** Blah blah JavaDoc.** @deprecated As of JDK version 1.1,*/
public class DeprecatedApi  {}

显然,这是一种非常脆弱的方法:唯一利用它的方法是通过javadoc工具。 标准JavaDocs 专门讨论了这些不推荐使用的API 。 或者,可以通过自定义doclet配置javadoc工具,以以任何所需方式处理Javadoc元数据(包括但不限于@deprecated )。

Java 5中,弃用使用提供的@Deprecated批注进行标记:

/*** Blah blah JavaDoc.*/
@Deprecated
public class DeprecatedApi  {}

注意: 旧的不推荐使用的API保留了旧的方法,因此它们同时使用元数据和注释。

此外,由于Java 9, @Deprecated允许两个元素:

  1. forRemoval (类型为boolean ):指示带注释的元素是否在将来的版本中会被删除
  2. since (类型为String):返回不支持带注释的元素的版本
@Deprecated (since= "1.2" , forRemoval= true )
public abstract class IdentityScope extends Identity  {}

创建注释

要创建注释,请使用@interface关键字:

public @interface MyAnnotation {}

但是,这还不够,因为不能在任何地方设置这样的注释。 注释需要另外两条信息:

  • 目标 :定义可以在何处设置注释
  • 保留 :这说明了注释在编译过程中的哪个步骤可用

稍后我们将详细介绍。 至于现在,我们首先需要
了解注释的工作方式。 虽然类从其继承代码
父类, 注释组成

@Target (ElementType.ANNOTATION_TYPE)  // 1     
@interface Foo {}@Target (ElementType.ANNOTATION_TYPE)  // 1   
@interface Bar {}@Foo
@Bar
@interface Baz {}                      // 2
  1. 这是必需的@Target ,将在@Target进一步解释
  2. @Baz注释的内容同时用@Foo@Bar注释

这是@Target@Retention的源代码:

@Retention (RetentionPolicy.RUNTIME)    // 2
@Target (ElementType.ANNOTATION_TYPE)   // 1
public @interface Target {           ElementType[] value();
} @Retention (RetentionPolicy.RUNTIME)   // 2
@Target (ElementType.ANNOTATION_TYPE)  // 1
public @interface Retention {        RetentionPolicy value () ;
}
  1. @Target注释告诉您可以在哪个元素上设置注释:
  • 在类型上, 例如类或接口
  • 在另一个注释上
  • 在田野上
  • 在方法上
  • 在构造函数上
  • 在方法参数上在局部变量上在模块上等
  1. @Retention注释定义了注释在编译过程中的哪个步骤可用:
  • 仅源代码
  • 在类文件中
  • 在运行时

下面的类图中对此进行了总结:

注释参数

注释可以定义参数 。 使用注释时,可以使用参数添加某些级别的配置。 参数接受类型和可选的默认值 。 如果在定义注释时未设置该值,则必须在使用它时使用。

参数类型限于以下几种:

  • 任何原始类型, 例如 intlong等。
  • String
  • Class<T>
  • 任何enum类型
  • 另一种注释类型
  • 以上任何数组
  • @Target (ElementType.CLASS)
    @interface Foo {int bar () ;Class<? extends Collection> baz() default List.class;String[] qux();
    } @Foo (bar = 1 , qux = { "a" , "b" , "c" })
    class MyClass  {}

    如果只有一个参数,并且它是命名值,则在设置时可以省略其名称:

    @Target (ElementType.CLASS)
    @interface Foo {int value () ;
    } @Foo ( 1 )
    class MyClass  {}

    在运行时处理批注:反射

    自创建以来,Java就允许反射 :反射是在运行时获取有关代码信息的能力。 这是一个示例:

    var session = request.getHttpSession();
    var object = session.getAttribute( "objet" );  // 1       
    var clazz = object.getClass();               // 2       
    var methods = clazz.getMethods();            // 3       
    for ( var method : methods) {if (method.getParameterCount() == 0 ) {   // 4       method.invoke(foo);                  // 5       }
    }
  1. 获取存储在会话中的对象
  2. 获取对象的运行时类
  3. 获取对象上所有可用的public方法
  4. 如果该方法没有参数
  5. 调用方法

通过注释,反射API得到了相关的改进:


注释,框架开始将它们用于不同的
用例。 其中,配置是最常用的配置之一:
例如, Spring框架代替了XML(或者更精确地说是XML之外),添加了基于注释的配置选项。

在编译时处理批注:批注处理器

长期以来,用户和提供者都对运行时反射对批注的访问感到满意。 因为它主要集中在配置上,所以反射在启动时发生。 在受限的环境中,这对应用程序来说负担太重:此类环境最著名的示例是Android平台。 人们可能希望在那里拥有最快的启动时间,而启动时间反射方法会使速度变慢。

解决该问题的另一种方法是在编译时处理注释 。 为此,必须将编译器配置为使用特定的注释处理器 。 它们的输出可能不同:简单的文件,生成的代码等。这种方法的权衡之处在于, 每次编译都会对性能造成影响,但不会影响启动时间。

使用此方法生成代码的最早框架之一是Dagger :它是Android的Dependency-Injection框架。 它不是基于运行时的,而是基于编译时的。 长期以来,编译时代码生成仅限于Android生态系统。

但是,最近,诸如Quarkus和Micronaut的后端框架
也采用了这种方法。 目的是通过编译时代码生成来代替运行时自省,以减少应用程序启动时间。 此外,将生成的字节码提前编译为本机代码还可以进一步减少启动时间以及内存消耗。

注释处理器的世界是巨大的:本节是一个但非常
简短的介绍,因此如果需要可以继续进行。

处理器只是需要在编译时注册的特定类。 有几种注册方法。 使用Maven,只需配置编译器插件即可:

< build >< plugins >< plugin >< groupId > org.apache.maven.plugins </ groupId >< artifactId > maven-compiler-plugin </ artifactId >< version > 3.8.1 </ version >< configuration >< annotationProcessors >< annotationProcessor >ch.frankel.blog.SampleProcessor</ annotationProcessor ></ annotationProcessors ></ configuration ></ plugin ></ plugins >
</ build >

处理器本身需要实现Processor ,但是抽象类AbstractProcessor实现其大多数方法,但可以进行处理:实际上,从AbstractProcessor继承就足够了。 这是API的简化图:

让我们创建一个非常简单的处理器。 它应该只列出那些
带有特定注释。 真实世界注解
处理器可能会做一些有用的事情, 例如生成代码,但是这种额外的逻辑远远超出了本文的范围。

@SupportedAnnotationTypes ( "ch.frankel.blog.*" )                  // 1          
@SupportedSourceVersion (SourceVersion.RELEASE_8)
public class SampleProcessor extends AbstractProcessor  {  @Overridepublic boolean process (Set<? extends TypeElement> annotations,// 2       RoundEnvironment env)  {annotations.forEach(annotation -> {                         // 3       Set<? extends Element> elements =env.getElementsAnnotatedWith(annotation); // 4elements.stream().filter(TypeElement.class::isInstance)                   // 5               .map(TypeElement.class::cast)                           // 6       .map(TypeElement::getQualifiedName)                      // 7       .map(name -> "Class " + name + " is annotated with " + annotation.getQualifiedName()).forEach(System.out::println);});return true ;}
}
  1. 属于ch.frankel.blog包的每个注释都将调用Processor
  2. process()是重写的主要方法
  3. 将为每个注释调用循环
  4. 注释不像使用注释的元素那么有趣。 这是获取带注释元素的方法。
  5. 根据要注释的元素,需要将其强制转换为正确的Element子接口。 在这里,只能注释类,因此,需要对变量进行测试,以检查其是否可分配的TypeElement才能在操作链的更下方访问其附加属性。
  6. 我们想要设置注释的类的限定名称,所以它是
    必须将其强制转换为构成此特定属性的类型
    无障碍
  7. TypeElement获取合格名称

结论

无论在运行时还是在编译时使用,注释都非常强大。 另一方面,最大的问题是它们似乎像魔术一样工作:没有简单的方法来知道哪个使用反射的类或注释处理器正在使用它们。 每个人都可以根据自己的情况决定自己的优点是否超过缺点。 在没有任何深思熟虑的情况下使用它们会对代码造成极大的损害...
由于放错位置而造成的损失与丢弃它们一样严重
思想。

我希望这篇文章对注释的工作方式有所启发,以便大家自己决定。

可以在Github上以Maven格式找到此帖子的完整源代码。

更进一步:

  • Java中的标记接口
  • Doclet概述
  • Java语言规范:注释类型
  • Java语言规范:注释
  • Trail:反射API
  • Java注释处理和创建生成器

首次发布于2020年4月26日于 A Java Geek

翻译自: https://hackernoon.com/a-beginners-guide-to-annotations-and-annotation-processors-explained-wu6r321s

excel批注不显示批注框


http://chatgpt.dhexx.cn/article/EW1AhPUn.shtml

相关文章

Error LNK2005 DllMain already defined in dllmain.obj

问题描述&#xff1a; 在创建Win32动态库时&#xff0c;使用了MFC库。 原因分析&#xff1a; MFC库中存在DllMain&#xff0c;与现有的DllMain重复 解决方案&#xff1a; 1.删除现有的DllMain函数 2.在工程设置里面&#xff0c;把WIN32,NDEBUG,_WINDOWS,_MBCS,_USRDLL,MS…

C++-导出类-导出宏-纯虚函数-DllMain函数-调用约定与参数命名

文章目录 1.普通类导出2.接口类导出3.调用约定与参数命名4.名字修饰约定5.MFC导出宏6.DLLMain函数7.一个DLL在内存中只有一个实例 在编写应用软件时&#xff0c;代码重用是非常关键的一步&#xff0c;C编程语言里&#xff0c;为了使编写的dll文件&#xff0c;能够实现重用&…

9.DLL的入口函数DllMain函数

1.dll的入口函数 类似程序的入口函数main或者WinMain一样&#xff0c;DLL也有一个入口函数&#xff0c;就是DllMain 2.DllMain函数原型 BOOL APIENTRY DllMain( HMODULE hModule, //指向自身的句柄DWORD ul_reason_for_call, //调用原因LPVOID lpReserved …

导致DllMain中死锁的关键隐藏因子

原文地址&#xff1a;https://blog.csdn.net/hczhiyue/article/details/18505087 有了前面两节的基础&#xff0c;我们现在切入正题&#xff1a;研究下DllMain为什么会因为不当操作导致死锁的问题。首先我们看一段比较经典的“DllMain中死锁”代码。 //主线程中 HMODULE h …

DllMain详解

DllMain详解 源码下载&#xff1a; DLL – 动态链接库 DllMainTest – 测试DLL的DllMain 1 DLL的进入/退出函数 1.1 DllMain简介 跟exe有个main或者WinMain入口函数一样&#xff0c;DLL也有一个入口函数&#xff0c;就是DllMain。以“DllMain”为关键字&#xff0c;来看看MSD…

Flash 加密和破解

关于Flash&#xff08;swf&#xff09;&#xff0c;我们需要明确一点&#xff1a; ***Flash字节码的意义都是公开的 所以如果cracker真的有足够的耐心他最终还是可以破解掉你的Flash。我们能做的只是尽量提高Flash被破解的门槛让cracker破解它需要消耗的时间大于自己更新版本的…

flashfxp是ftp软件吗,你知道flashfxp是ftp软件吗

flashfxp是ftp软件吗&#xff1f;当然。ftp是一种文件传输协议&#xff0c;用于互联网双向传输&#xff0c;控制文件下载空间在服务器复制文件从本地计算机或本地上传文件复制到服务器上。而FlashFXP是一款功能强大的FXP/FTP软件&#xff0c;集成了其它优秀的FTP软件的优点&…

pfx证书解析公钥私钥

从pfx中获取CA证书 openssl pkcs12 -in test.pfx -nodes -out server.pem 输入证书密码 提取公钥 X.509格式 openssl x509 -in server.pem -out public.cer RSA格式 openssl rsa -in server.pem -outform PEM -pubout -out public.pem 提取私钥 openssl rsa -in server…

提权学习:第三方软件提权(FlashFXP 替换文件漏洞提权)

当你的才华 还撑不起你的野心时 那你就应该静下心来学习 目录 FlashFXP 替换文件漏洞提权 0x01 前言 介绍 用途 特点 0x02 环境配置 0x03 FlashFXP 提权思维导图 0x04 操作演示 FlashFXP 替换文件漏洞提权 0x01 前言 介绍 FlashFXP是一个功能强大的 FXP/FTP 软件&…

用FlashFXP上传文件到SSH服务器,附FlashFXP显示中文乱码的解决方法

用SSH Secure Shell能上传文件&#xff0c;又能输入命令&#xff0c;而且上传文件的时候不容易无故断开连接。但是它缺少续传的功能&#xff0c;不太适合上传比较大的文件&#xff1b;而且它在与linux系统SSH登陆时不方便支持中文&#xff0c;所以这里我向大家推荐FlashFXP来实…

flashfxp链接Linux

使用FLASHFXP链接我们的Linux操作系统&#xff0c;可以方便实现文件的上传下载到Linux中。在我们的Linux能成功链接网络后&#xff0c;利用ifconfig命令设置ip、掩码、网关。 设置ip与掩码&#xff1a;ifconfig eth0 192.168.1.114 netmask 255.255.255.0&#xff0c;设置网关…

FlashFXP使用阿里云ECS私钥登录

前言 最近购买了一个阿里云服务器主机&#xff0c;需要使用到FTP上传文件到服务器&#xff0c;因为我一直习惯使用FlashFXP上传文件&#xff0c;使用的是SFTP,所以没有在额外的安装FTP的服务&#xff0c;但是发现阿里云的ECS在SFTP模式下直接使用密码和用户名登录会报错。下面是…

NET主流ORM框架分析

接上文我们测试了各个ORM框架的性能&#xff0c;大家可以很直观的看到各个ORM框架与原生的ADO.NET在境删改查的性能差异。这里和大家分享下我对ORM框架的理解及一些使用经验。 ORM框架工作原理 所有的ORM框架的工作原理都离不开下面这张图&#xff0c;只是每个框架的实现程度不…

Linux USB总线驱动框架分析

1、USB驱动引入 USB&#xff08;全称 Universal Serial Bus&#xff0c;通用串行总线&#xff09;&#xff0c;已经成为PC及嵌入式设备中最常用、最便捷的通信接口。Linux USB子系统较为庞大&#xff0c;本文主要对Linux系统下的USB总线驱动框架进行概述&#xff0c;重点的细节…

Django框架详解

一、MVC框架 1、MVC框架核心思想&#xff1a; 分工和解耦 2、web MVC举例&#xff1a; 以通过浏览器注册用户信息为例&#xff1a; M:Model,模型&#xff0c; 和数据库进行交互。V:View,视图&#xff0c; 产生html页面。C:Controller,控制器, 接收请求&#xff0c;进行处…

几种数据可视化框架分析

根据下面各个框架本身的特性&#xff0c;以及各自的优缺点&#xff0c;推荐使用D3或者ECharts作为数据可视化的首选框架&#xff0c;某些小特性可以辅用其他小框架实现。具体每个框架的说明和分析如下&#xff1a; D3.js D3是指数据驱动文档(Data-Driven Documents)。D3.js是一…

常见威胁建模框架分析与比较

1 概述 威胁建模的方法最初是为了帮助开发更多的安全的操作系统&#xff0c;但已经开发的大量威胁建模方法&#xff0c;有些只关注软件发展&#xff0c;有些仅涵盖业务或组织的风险和威胁&#xff0c;另有一些可能是技术性的&#xff0c;不同的威胁模型都在基于不同的目的而开…

某商城框架分析

开篇 最近做了一个商城系统,从系统的需求,到系统的选型以及框架和各种技术的研究和使用,我都参与其中,所以,分享一下这个系统. 框架 框架如下: 说明: 表现层 用户分为两种&#xff0c;PC端用户和移动端用户; 其中PC端包括 商城首页,商品类目,购物车,订单,商品展示,会员中心等…

Cgroup框架分析

cgroups概念扫盲 关于cgroups本文主要分析的是cgroups整体框架&#xff0c;不涉及对各个子系统的介绍和cgroupsfs的介绍&#xff0c;在分析cgroup整体框架的时候&#xff0c;首先我们需要对cgroups中的一些概念有所深刻认识&#xff0c;只有在这个基础上&#xff0c;才能明白为…

音视频常见播放器框架分析

音视频面试必问&#xff1a;如何设计一个播放器 1.常见播放器框架分析 2.如何解决播放端延迟的问题 3.音视频如何做同步 4.快进、快退、逐帧播放如何实现 音视频开发技术精讲《常见播放器框架分析》 播放器框架 SDL2播放音频 使用SDL播放解码后的音频数据&#xff0c;SDL播放…