注解为何在运行时消失?深入字节码解析Java注解保留策略的底层机制

第一章:注解为何在运行时消失?现象与核心问题

Java 注解(Annotation)在开发中广泛用于元数据描述,但许多开发者常遇到一个困惑:明明在代码中定义了注解,为何在程序运行时却无法获取?这种“消失”现象的根本原因在于注解的**保留策略(Retention Policy)**未正确配置。

注解的生命周期由保留策略决定

Java 提供三种内置的 RetentionPolicy:
  • SOURCE:仅保留在源码阶段,编译期即丢弃
  • CLASS:保留在字节码文件中,但 JVM 运行时不会加载
  • RUNTIME:保留在运行时,可通过反射访问
若未显式指定 @Retention(RetentionPolicy.RUNTIME),注解默认可能不保留至运行期,导致反射调用 getAnnotations() 返回空数组。

示例:运行时不可见的注解

// 缺少 @Retention(RUNTIME),运行时无法读取
@interface MyAnnotation {
    String value();
}

public class Test {
    @MyAnnotation("test")
    public void doSomething() {}

    public static void main(String[] args) throws Exception {
        var method = Test.class.getMethod("doSomething");
        var ann = method.getAnnotation(MyAnnotation.class);
        System.out.println(ann); // 输出:null
    }
}
上述代码中,尽管方法上标注了注解,但由于未设置运行时保留策略,反射获取结果为 null。

关键检查点

检查项说明
@Retention 设置必须使用 RUNTIME 策略才能在运行时读取
反射调用时机确保在类加载后、方法执行前进行注解扫描
注解目标支持确认注解声明时允许出现在类、方法等目标上(@Target)

第二章:Java注解基础与保留策略详解

2.1 注解的定义与元注解的作用机制

注解(Annotation)是Java中用于为代码添加元数据的一种机制,它不直接影响程序逻辑,但可被编译器、开发工具或运行时环境解析并执行相应操作。
元注解的核心角色
元注解是用于修饰其他注解的特殊注解,主要定义在 java.lang.annotation 包中。常见的元注解包括:
  • @Target:指定注解的应用范围,如类、方法或参数;
  • @Retention:控制注解的生命周期,可设置为源码、类文件或运行时可见;
  • @Documented:表示注解应包含在JavaDoc中;
  • @Inherited:允许子类继承父类的注解。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecution {
    String value() default "execution";
}
上述代码定义了一个自定义注解 @LogExecution,仅适用于方法,并在运行时可通过反射读取。其中 value() 为注解成员,提供默认值,调用时可简写为 @LogExecution("saveUser")。

2.2 @Retention元注解与三种保留策略解析

注解的生命周期控制

@Retention 元注解用于指定注解的保留策略,决定注解在源码、编译或运行时是否保留。其值类型为 RetentionPolicy 枚举,包含三种策略。

  • SOURCE:仅保留在源码阶段,编译时被丢弃;
  • CLASS:保留在字节码文件中,但JVM运行时不加载;
  • RUNTIME:保留至运行期,可通过反射读取。
代码示例与分析
@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable {
    String value() default "INFO";
}

上述注解使用 RetentionPolicy.RUNTIME,意味着在程序运行时仍可通过反射获取该注解信息,适用于AOP日志、权限校验等场景。若未指定保留策略,默认使用 CLASS 策略,限制了注解的可用性。

策略源码保留字节码保留运行期可读
SOURCE是否否
CLASS是是否
RUNTIME是是是

2.3 编译期处理:源码级与类文件中的注解表现

在Java编译过程中,注解根据生命周期可分为源码级和类文件级两类。源码级注解仅保留在源代码中,由注解处理器在编译期解析并生成额外代码。
注解处理器的介入时机
编译器在解析Java源文件时,会触发注册的注解处理器(javax.annotation.processing.Processor),对带有特定注解的元素进行检查或代码生成。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface GenerateBuilder { }
该注解使用SOURCE保留策略,仅存在于源码阶段,不进入类文件,常用于Lombok等工具实现语法增强。
类文件中的注解表现
当注解声明为RetentionPolicy.CLASS或RetentionPolicy.RUNTIME时,编译器将其写入类文件的RuntimeVisibleAnnotations属性中,供后续字节码分析或反射调用使用。
保留策略源码可见类文件可见运行时可见
SOURCE是否否
CLASS是是否
RUNTIME是是是

2.4 实验验证:通过javac与javap观察不同策略的字节码差异

为了深入理解Java编译器对不同代码结构的处理方式,可通过`javac`编译源码并使用`javap`反汇编查看生成的字节码。
实验准备
编写两个简单类,分别采用普通变量访问与volatile修饰符:
public class VolatileExample {
    private volatile int flag = 0;
    public void setFlag() {
        flag = 1;
    }
}
public class NormalExample {
    private int flag = 0;
    public void setFlag() {
        flag = 1;
    }
}
字节码对比分析
使用命令:javac *.java 编译后,执行 javap -c VolatileExample NormalExample 查看指令序列。
操作NormalExampleVolatileExample
写入flagputfieldputfield + volatile语义屏障
`volatile`字段的读写会插入内存屏障指令,确保可见性与有序性,这在字节码层面虽不直接体现,但可通过运行时行为和JVM规范验证其存在。

2.5 运行时不可见的根本原因:CLASS与SOURCE策略的生命周期终结

Java注解的保留策略决定了其在编译和运行时的可见性。使用RetentionPolicy.CLASS或SOURCE的注解在类文件生成后即被丢弃,无法通过反射获取。
三种保留策略对比
策略源码期可见编译期可见运行期可见
SOURCE是否否
CLASS是是否
RUNTIME是是是
代码示例
@Retention(RetentionPolicy.SOURCE)
public @interface BuildTimeOnly {}

@Retention(RetentionPolicy.CLASS)
class HiddenAnnotation {}
上述注解在.class文件中不保留元数据,导致运行时框架无法感知其存在,这是许多AOP或依赖注入失效的根本原因。

第三章:反射与运行时注解的获取机制

3.1 Java反射API中获取注解的方法与限制

Java反射API提供了多种方法来获取类、方法、字段等元素上的注解。最常用的是通过 getAnnotation(Class<T>) 和 getAnnotations() 方法。
常用获取注解的反射方法
  • isAnnotationPresent(Class<T> annotationClass):判断是否含有指定注解;
  • getAnnotation(Class<T>):返回指定类型的注解;
  • getDeclaredAnnotations():返回本元素上直接声明的所有注解。
@Retention(RetentionPolicy.RUNTIME)
@interface Version {
    int value();
}

public class Example {
    @Version(2)
    private String data;
}

// 反射读取注解
Field field = Example.class.getDeclaredField("data");
if (field.isAnnotationPresent(Version.class)) {
    Version version = field.getAnnotation(Version.class);
    System.out.println(version.value()); // 输出: 2
}
上述代码中,只有被 @Retention(RUNTIME) 修饰的注解才能通过反射获取。若注解的保留策略为 SOURCE 或 CLASS,则无法在运行时访问。
主要限制
注解的可见性受其 @Retention 策略限制,且泛型擦除也会影响参数化类型的注解处理。此外,私有成员的注解需通过 getDeclaredFields() 获取,无法通过继承获得父类方法上的注解(除非使用框架增强)。

3.2 实践演示:通过反射读取RUNTIME级别注解的完整流程

在Java中,RUNTIME级别的注解可通过反射机制在运行时动态读取,适用于配置解析、框架扩展等场景。
定义运行时注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecution {
    String value() default "执行日志";
}
该注解使用@Retention(RetentionPolicy.RUNTIME)确保保留在字节码中,并可通过反射访问。
应用注解并读取
public class Service {
    @LogExecution("用户登录")
    public void login() { }
}

// 反射读取
Method method = Service.class.getMethod("login");
if (method.isAnnotationPresent(LogExecution.class)) {
    LogExecution ann = method.getAnnotation(LogExecution.class);
    System.out.println(ann.value()); // 输出:用户登录
}
通过getAnnotation()获取注解实例,进而访问其属性值,实现运行时行为控制。

3.3 深入Class文件结构:注解信息在运行时的存储位置分析

Java Class文件中的注解信息主要存储在RuntimeVisibleAnnotations和RuntimeInvisibleAnnotations属性中,位于字段、方法或类的属性表内。
注解的存储结构
  • RuntimeVisibleAnnotations:在运行时可通过反射访问的注解
  • RuntimeInvisibleAnnotations:仅编译期使用,不会加载到JVM运行时
字节码中的注解示例

@Retention(RetentionPolicy.RUNTIME)
public @interface Monitor {
    String value();
}
该注解被标记为RUNTIME,其元数据将写入Class文件的RuntimeVisibleAnnotations属性中。
属性表结构示意
属性名称作用目标是否运行时可见
RuntimeVisibleAnnotations类/方法/字段是
RuntimeInvisibleAnnotations类/方法/字段否
JVM在类加载时解析这些属性,并通过java.lang.reflect.AnnotatedElement接口暴露给反射调用。

第四章:字节码层面剖析注解的留存轨迹

4.1 使用ASM或Javap解析class文件中的注解属性

在Java字节码层面解析注解,ASM和`javap`是两种高效手段。ASM通过访问类结构动态提取注解信息,适合集成到构建工具中。
使用ASM读取注解
ClassReader cr = new ClassReader("com.example.MyClass");
cr.accept(new ClassVisitor(Opcodes.ASM9) {
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
        System.out.println("Found annotation: " + desc);
        return super.visitAnnotation(desc, visible);
    }
}, 0);
上述代码通过`ClassReader`加载类,并注册`ClassVisitor`监听注解事件。`desc`为注解类型的内部名称,需转换为可读格式。
使用javap命令行分析
执行`javap -v MyClass.class`可输出详细字节码,包含注解声明:
  • 输出包含RuntimeVisibleAnnotations属性
  • 展示注解类型及成员值
  • 适用于快速调试与验证

4.2 RuntimeVisibleAnnotations与RuntimeInvisibleAnnotations对比分析

Java字节码中,注解的可见性由其目标存储区域决定。`RuntimeVisibleAnnotations` 和 `RuntimeInvisibleAnnotations` 是类文件结构中的两个属性,分别控制注解在运行时是否可见。
核心差异
  • RuntimeVisibleAnnotations:注解保留在字节码中,并可通过反射获取;适用于如 @Override、自定义AOP切面等场景。
  • RuntimeInvisibleAnnotations:注解仅在编译期有效,不会被加载到JVM运行时,例如 @SuppressWarnings。
字节码示例

@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable { }

@Retention(RetentionPolicy.CLASS)
public @interface CompileTimeOnly { }
上述代码中,@Loggable 将写入 RuntimeVisibleAnnotations,而 @CompileTimeOnly 存储于 RuntimeInvisibleAnnotations,不被反射读取。
性能与设计考量
保留注解会增加类文件体积并影响反射开销。应根据实际需求选择保留策略,避免不必要的运行时负担。

4.3 字段、方法、类级别注解在字节码中的存储方式

Java 注解在编译后以特定结构存储于字节码的属性表中,主要通过 `RuntimeVisibleAnnotations` 和 `RuntimeInvisibleAnnotations` 属性保存。
注解的字节码结构
每个类、字段或方法的注解信息被编码为 `annotation` 结构数组,包含注解类型索引和成员值对。例如:
public @interface Deprecated {
    String since() default "";
}
该注解若应用于方法,编译后会在该方法的 `RuntimeVisibleAnnotations` 属性中生成对应条目,记录注解类型符号引用及 `since` 成员的默认值。
字节码属性表中的存储位置
  • 类级别的注解存储在类文件的 attributes 表中
  • 字段和方法的注解分别位于其 field_info 和 method_info 的属性表内
  • 每个注解条目包含类型描述符和 element_value_pairs
这些结构确保 JVM 在运行时可通过反射机制还原注解信息,支撑框架如 Spring 的依赖注入与 JPA 的映射解析。

4.4 动态代理结合注解:展示运行时注解的实际应用场景

在Java中,动态代理与注解的结合可用于实现灵活的横切关注点控制,如日志记录、权限校验等。
定义自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecution {
    String value() default "";
}
该注解在运行时保留,用于标记需要记录执行时间的方法。
动态代理拦截处理
  • 通过InvocationHandler捕获方法调用
  • 利用反射检查方法是否标注@LogExecution
  • 在方法执行前后插入监控逻辑
Object invoke(Object proxy, Method method, Object[] args) {
    if (method.isAnnotationPresent(LogExecution.class)) {
        System.out.println("开始执行: " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("执行结束");
        return result;
    }
    return method.invoke(target, args);
}
上述代码展示了如何在代理中解析注解并增强行为,实现非侵入式功能扩展。

第五章:从机制到设计——合理使用注解保留策略的工程建议

在大型Java项目中,注解不仅是元数据的载体,更是架构设计的重要组成部分。合理选择注解的保留策略(Retention Policy)直接影响运行时性能、调试效率与框架扩展性。
明确注解用途决定保留级别
  • SOURCE:适用于编译期检查或代码生成,如 Lombok 的 @Data,避免运行时开销;
  • CLASS:适用于字节码处理工具,如 ASM 或某些 AOP 框架,在类加载阶段读取;
  • RUNTIME:用于反射驱动的框架,如 Spring 的 @Component 或 JPA 的 @Entity。
避免过度使用RUNTIME注解
// 错误示例:将仅用于编译的校验注解设为RUNTIME
@Retention(RetentionPolicy.RUNTIME)
@interface NotNull {}

// 正确做法:若仅用于编译器检查,应设为SOURCE
@Retention(RetentionPolicy.SOURCE)
@interface NotNull {}
构建可维护的注解体系
场景推荐策略典型应用
依赖注入配置RUNTIMESpring @Autowired
序列化字段标记CLASSJackson @JsonProperty
空值检查注解SOURCEIDE 静态分析支持
结合AOP与注解实现日志追踪
使用 RUNTIME 注解标记关键服务方法,配合 Spring AOP 在运行时织入日志逻辑:
@Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.METHOD)
  public @interface LogExecution {}
  
AOP 切面通过反射判断该注解是否存在,决定是否记录执行时间。
Java反编译器原理与实战:从字节码到可读源码的四层解析 Java反编译器是理解JVM字节码与高级语言语义映射关系的关键工具,其本质是基于JVM规范的结构化逆向解析系统。它通过字节码解析、控制流图构建、抽象语法树重构和源码格式化四个确定性层级,将.class文件转化为人类可读的Java逻辑。这一过程不依赖AI猜测,而是严格遵循编译器行为与字节码语义,支撑着第三方库调试、JDK源码探究、二进制兼容性审计及安全漏洞扫描等核心工程实践。尤其在源码缺失或黑盒依赖场景下,CFR、Procyon等主流工具通过差异化引擎设计,在泛型推断、Lambda还原与混淆对抗等方面提供可信 阅读详情

相关推荐

Java @Retention 注解:让你的代码穿越时空的秘密武器

Java的@Retention注解是控制注解生命周期的强大工具。它决定了注解在源代码、字节码或运行时的可见性,帮助开发者灵活地管理元数据,提升代码的可读性和维护性。让你的代码如时间旅行般无所不在!

专注于深入研究多种编程语言,以实战为导向,逐步拓展开发技能,提升工程化编码和思维能力,展现无敌技术实力。 413

Java注解本质与底层机制

Java注解本质是继承自Annotation的特殊接口,其生命周期由@Retention元注解控制,分为SOURCE、CLASS、RUNTIME三种策略。SOURCE仅作用于源码阶段,CLASS保留在字节码中但运行时不可见,RUNTIME则在运行时可通过反射获取。不同策略对应不同处理机制:SOURCE依赖注解处理器进行编译期检查或代码生成,CLASS通过字节码工具处理,RUNTIME则利用反射实现运行时行为控制。这种分层设计使注解能够灵活应用于语法检查、字节码增强和依赖注入等场景。

JasmineWr的博客 966

自监督学习与上下文赌博机融合:视觉决策中的协同优化与实战指南

在机器学习领域,自监督学习(Self-Supervised Learning)通过设计前置任务从无标注数据中学习通用表征,已成为解决标注数据稀缺问题的关键技术。其核心原理是利用数据自身的结构生成监督信号,训练编码器提取鲁棒特征。上下文赌博机(Contextual Bandits)作为强化学习的简化分支,专注于在给定上下文信息下做出单步最优决策,平衡探索与利用,广泛应用于推荐系统、广告投放等场景。将两者结合,构建端到端的协同训练框架,能让视觉表征的优化直接服务于最终的决策目标,同时利用自监督任务作为正则化项提

weixin_33721344的博客 520

【架构师必备知识】:从源码级别剖析Java注解保留策略的设计哲学

深入解析Java反射的注解保留策略,揭示源码层面的设计逻辑与应用场景。涵盖RUNTIME、CLASS、SOURCE策略差异及在框架开发中的实际应用,助你掌握动态读取注解的核心方法。架构设计更灵活,值得收藏。

CompiGap的博客 814

STM32驱动AD2S1210实现旋变解码与角度读取

旋转变压器作为一种耐高温、抗振动的角度传感器,在工业伺服、机器人关节和电动汽车电驱等场景中占据重要地位。其输出信号需要经过专用转换芯片处理才能被MCU高效使用。AD2S1210是一款典型的旋变数字转换器(RDC),内部采用Type II型跟踪环,将模拟SIN/COS信号实时解算为数字角度与速度,降低了处理器负担并提升抗干扰能力。本文基于STM32平台,详细介绍了AD2S1210的硬件接线、SPI通信配置、寄存器初始化流程,以及读取位置数据时的SAMPLE脉冲时序等关键实现。同时总结了常见故障如全FF、角度跳

weixin_34194829的博客 194

STM32F407通过SMBus协议精准读取BQ40Z50电池电量

本文详细介绍了STM32F407通过SMBus协议精准读取BQ40Z50电池电量的实现方法。从硬件连接到软件驱动开发,再到通信异常排查,提供了完整的解决方案。重点解析了SMBus协议的特殊时序要求、GPIO模拟驱动的关键代码,以及实际调试中的常见问题与对策,帮助开发者高效完成电池管理系统开发。

weixin_29189003的博客 253

Java注解机制详解:从自定义注解到运行时应用

Java注解是Java5引入的元数据机制,用于为代码元素添加结构化信息。摘要涵盖:1)注解基本语法与元注解(@Target、@Retention等);2)三种保留策略(SOURCE/CLASS/RUNTIME)及其应用场景;3)自定义业务注解与AOP集成示例;4)注解设计原则与性能考量。注解通过编译时检查、运行时反射和切面编程,实现了代码语义扩展、行为控制和框架扩展能力,开发者需根据需求合理选择保留策略,平衡功能与性能。

2501_92314142的博客 649

【js逆向学习】新手视角破解「广东省公共资源交易平台」

学习js逆向,破解广东省公共资源交易平台,详细记录个人探索、踩坑全过程。网站地址: aHR0cHM6Ly95Z3AuZ2R6d2Z3Lmdvdi5jbi8jLzQ0L2p5Z2c=仅供学习参考,如有疑问欢迎交流,一起学习进步。

DCSDA的博客 3320

注解为何在运行时“消失”?深入字节码揭开SOURCE与CLASS的秘密

揭秘注解在运行时“消失”的原因,深入解析反射注解的 RetentionPolicy 机制。涵盖 SOURCE、CLASS、RUNTIME 的适用场景与字节码差异,揭示注解生命周期控制的关键优势。理解三者区别,提升框架设计能力,值得收藏。

AlgoInk的博客 465

11、牛转录组分析的实用生物信息学流程

本文详细介绍了一套实用的牛转录组分析生物信息学流程,涵盖从数据提取、基因组索引生成、读取比对到单样本表达分析及差异表达分析的完整步骤。使用Angus和Brahman牛的RNA-seq数据作为示例,介绍了HTSEQ、featureCounts和StringTie等工具在基因表达计数中的应用,并结合edgeR和limma进行差异表达分析。文中提供了详细的命令行与R代码示例,包含常见问题解答与关键注意事项,帮助研究人员高效、准确地完成转录组数据分析。

ios99的博客 111

Avalonia+ReactiveUI跨平台路由:从零到舞者,你的UI也能跨界起舞?

至此,你已掌握了Avalonia+ReactiveUI的跨平台路由精髓!你的应用现在能够优雅地在各个界面间穿梭,就像是在不同星球间跳跃的宇宙飞船。无论是初探跨平台开发的新手,还是经验丰富的老船长,这段旅程都能让你的UI编排技能更上一层楼。现在,是时候让世界见证你的跨平台魔术了!💫记住,每一次实践都是向着完美编舞迈进的一步,勇敢地在你的项目中尝试吧!如果在航行中遇到风暴,别忘了回来看看这篇指南,或者在评论区抛出你的救生圈,我们一起解决!🌊。

java专栏 1534

反射中注解失效?只因你没搞懂这3个保留策略

掌握反射注解的 RetentionPolicy,彻底解决注解运行时失效问题。详解SOURCE、CLASS、RUNTIME三种保留策略的应用场景与区别,揭示反射获取注解的关键条件。理解RUNTIME策略的核心作用,提升代码动态处理能力,值得收藏。

CodeTrick的博客 294

华为OD机试双机位C卷:日志排序 (Py/C/C++/Java/Js/Go)

华为OD机试双机C卷真题【日志排序】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解。华为OD机试-日志排序。

qq_45776114的博客 1754

(Java基础)注解的底层原理

层面原理语法层注解是继承Annotation接口的特殊接口存储层注解数据保存在.class文件的元数据中运行层JVM 通过反射创建代理对象来读取注解值框架层框架根据注解类型执行对应逻辑(依赖注入、事务、AOP 等)注解本质是继承Annotation接口的特殊接口信息保存在字节码中,JVM 通过反射 + 动态代理读取注解数据,框架再根据这些注解执行对应逻辑。注解本身不执行任何操作,真正让它生效的是反射和框架。

savemeill的博客 393

【EPS精品教程】EPS2016三维测图版安装教程(附EPS2016安装包下载地址)

EPS地理信息工作站是北京清华山维新技术开发有限公司历经十五年精心研发和打造,为满足“以地理信息服务为中心”的信息化测绘生产需求而推出的测绘生产活动多种业务模块集成化软件系统。主要功能有:(1)测绘与地理信息多业务模块集成管理;(2)多元多尺度多种类数据集成管理;(3)跨平台异构数据转换;(4)数据监理;(5)自动缩编与综合;(6)坐标转换与动态投影;(7)地理信息模板定制;(8)GIS地理信息描述与CAD图形表达一体化支持;(9)GIS数据库更新维护;(10)图形打印与地图出版。 一、安装过程 EP..

智慧空间实验室 2万+

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Java注解机制深度解析:从元数据定义到反射与字节码增强实践

在Java开发中,元数据机制为代码提供了丰富的附加信息描述能力,注解(Annotation)正是这一机制的核心实现。其本质是一种特殊的接口,通过@Target、@Retention等元注解定义作用范围与生命周期,并以内置属性形式存储在Class文件的属性表中。这一设计使得注解能够在编译时、类加载时及运行时被处理,为框架开发与工程实践提供了强大的扩展能力。通过反射API,程序可以在运行时动态读取RUNTIME级别注解,实现依赖注入、配置映射等核心功能;而借助APT注解处理器与ASM、Byte Buddy等字节

weixin_30460489的博客 421

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

蚂蚁Java面试被问:注解的工作原理及如何自定义注解

本文系统介绍了Java注解的核心概念与应用。主要内容包括:1)注解本质是继承Annotation的接口,分为标记、单值和完整三类;2)元注解详解(@Target、@Retention、@Documented等);3)注解处理机制(编译时、运行时和字节码操作);4)四大实战场景(验证、AOP、ORM和配置);5)高级特性与最佳实践(性能优化、安全考虑和新特性结合)。文章强调应根据需求选择合适保留策略,避免过度设计,并提供了缓存反射、APT处理等优化建议,指导开发者合理运用注解提升代码质量。

x2277659985的博客 1010

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Java注解详解

本文介绍了Java注解的基本概念和使用方法。注解是一种特殊标记,用于为程序提供额外信息,指导编译器或框架执行特定操作。文章首先说明注解可以应用在类、方法、变量等多个位置,详细讲解了自定义注解的语法格式,包括属性声明和元注解(如@Target和@Retention)的使用。

2402_83593125的博客 901

Java注解 解析

java注解: Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。 注解是元数据的一种形式,提供有关 于程序但不属于程序本身的数据。注解对它们注解的代码的操作没有直接影响。 注解申明 Java中所有的注解,默认实现 Annotation 接口: package java.lang.annotation; public interface Annotation { boolean equals(Object obj...

a296191519的专栏 195

Java注解Retention完全解析:注解生命周期与反射的基石

在Java与Android开发中,自定义注解已成为提升编码效率与框架设计能力的关键技术,而注解的生命周期管理则由Retention机制决定。RetentionPolicy定义了注解从源码到运行期的存活范围,SOURCE、CLASS与RUNTIME分别对应编译前检查、字节码增强及运行时反射读取。理解其底层原理,例如JVM中RuntimeVisibleAnnotations与RuntimeInvisibleAnnotations的存储差异,有助于开发者避免“反射拿不到注解”或“Release包功能失效”等高频问

weixin_32576389的博客 94

java注解详解

java注解了解一下

weixin_42330641的博客 2964

Java之注解

关于java注解及其使用场景的简单介绍

lanjianta的博客 298

[Java面试基础]注解、反射详解

注解和运用注解编程 内容: 注解的作用 注解的本质 反射注解信息 元注解 属性的数据类型及特别的属性:value数组 反射机制概述 类的加载与ClassLoader 理解Class类并获取Class实例 注解的作用 格式 public @interface 注解名称{ 属性列表; } 格式有点奇怪,我们稍后再研究。 分类 大致分为三类:自定义注解、JDK内置注解、还有第三方框架提供的注解。 自定义注解就是我们自己写的注解。JDK内置注解,比如@Override检

lawfree的博客 583

一篇搞懂 Java 注解:从基础到实战,新手也能轻松上手

理解了元注解,自定义注解就非常简单了。注解的定义语法和接口类似,只是多了使用@interface关键字定义注解;添加元注解(指定@Target和@Retention定义注解的属性(可选,类似接口的方法)。需求:定义一个@Table注解,用于标记 Java 类对应的数据库表名。// 元注解:指定注解作用于类// 元注解:运行时保留,可通过反射获取// 生成javadoc时包含该注解// 注解的属性:表名,设置默认值为"default_table"注解属性的说明。

2302_80192044的博客 1047

Java 高级特性——注解

简介 Java注解(Annotation)又称 Java 标注,是JDK1.5 引入的一种注释机制。 和 Javadoc(注释)不同,Java 标注可以通过反射获取标注内容。在编译期生成类文件时,标注可以被嵌入到字节码中。 JVM 可以保留注释内容,在运行时可以获取到注释内容。当然它也支持自定义Java注释。 理解 Annotation 的关键,是理解 Annotation 的语法和用法;理解 Annotation 的语法和用法之后,再看 Annotation 的框架图,可能有更深刻的体会。 注解的分类

weixin_44471490的博客 886

Java入门到精通-30 注解与元编程

本文介绍了Java中的注解与元编程机制。主要内容包括: 注解本质:注解是结构化附加信息的接口,可用于编译检查、代码生成、运行时处理和文档生成。 内置注解: @Override、@Deprecated、@SuppressWarnings等常见注解 Java 9增强的@Deprecated新增属性 元注解:用于定义注解行为的注解: @Target指定作用范围 @Retention控制生命周期 @Repeatable实现重复注解 其他元注解如@Documented和@Inherited 应用示例:通过@Repea

weixin_56693899的博客 336
上一篇: Java TreeMap中的comparator究竟如何工作?99%的开发者都忽略了这一点
下一篇: Java并发编程核心技巧(Exchanger超时实战避坑指南)
FastCompile
博客等级 码龄1年 164粉丝 2015原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值