Java注解
1. 注解入门
1.1 Annotation
- 位于源码中(代码/注释/注解),使用其他工具进行处理的标签
- 注解用来修饰程序的元素,但不会对被修饰的对象有直接的影响
- 只有通过某种配套的工具才会对注解信息进行访问和处理
- 主要用途
- 提供信息给编译器/IDE工具
- 可用于其他工具来产生额外的代码/配置文件等
- 有一些注解可在程序运行时访问,增加程序的动态性
1.2 JDK预定义的普通注释(部分)
- @Override 表示继承和改写
- @Deprecated 表示废弃
- @SuppressWarnings 表示压制告警
- @SafeVarags 不会对不定项参数做危险操作
- @FunctionInterface 声明功能性接口
1.3 JDK预定义的元注解(部分)
元注解:修饰注解的注解
- @Target 设置目标范围
- @Retention 设置保持性
- RetentionPolicy.SOURCE 注解仅存在源码,不在class文件
- RetentionPolicy.CLASS 默认的注解保留策略,注解存在于class文件,但是不能被JVM加载
- RetentionPolicy.RUNTIME 注解可以被JVM运行时访问到,通常情况下,可以结合反射来做一些事情
- @Documented 文档 (指明这个注解可以被Javadoc工具解析,形成帮助文档)
- @Inherited 注解继承 (让一个类和它的子类都包含某个注解,普通的注解没有继承功能)
- @Repeatable 此注解可以重复修饰
1.4 自定义注解
- 注解可以包括的类型
- 8种基本类型(int/short/long/float/double/byte/char/boolean)
- String
- Class
- enum类型
- 注解类型
- 由前面类别组成的数组
- 自定义注解
- 扩展于java.lang.annotaion.Annotation
- 成员可以包括多种类型
- 使用时可以给注解成员赋值
- 用于修饰多种程序元素
2. 注解的解析
2.1 生命周期
- RetentionPolicy.RUNTIME注解采用反射进行解析
- RetentionPolicy.CLASS注解采用专用的字节码工具进行解析
- RetentionPolicy.SOURCE注解采用注解处理器进行解析
- 注解处理器继承AbstractProcessor,重写process方法
- java -processor Processor1,Proccessor2,... sourceJavaFile
2.1 反射解析RUNTIME注解
3. RUNTIME注解实现本质
3.1 RUNTIME注解调用路线
- 注解采用接口中的方法来表示变量
- Java为注解产生一个代理类,这个代理类包括一个AnnotationInvocationHandler成员变量
- AnnotationInvocationHandler有一个Map的成员变量,用来存储所有的注解的属性赋值
- 在程序中,调用注解接口的方法,将会被代理类接管,然后根据方法名字,到Map里面拿相应的Value并返回
3.2 RUNTIME注解的设计思路
-
传统的接口中的变量,都是public final static
-
注解需要随意赋值
- 注解方法表示变量
- 采用代理类拦截注解方法访问
- 所有注解的赋值,都放在Map中,访问速度快
-
AnnotationInvocationHandler
public Object invoke(Object proxy, Method method, Object[] args) { String member = method.getName(); int parameterCount = method.getParameterCount(); if (parameterCount == 1 && member == "equals" && method.getParameterTypes()[0] == Object.class) { return this.equalsImpl(proxy, args[0]); } else if (parameterCount != 0) { throw new AssertionError("Too many parameters for an annotation method"); } else if (member == "toString") { return this.toStringImpl(); } else if (member == "hashCode") { return this.hashCodeImpl(); } else if (member == "annotationType") { return this.type; } else { Object result = this.memberValues.get(member); if (result == null) { throw new IncompleteAnnotationException(this.type, member); } else if (result instanceof ExceptionProxy) { throw ((ExceptionProxy)result).generateException(); } else { if (result.getClass().isArray() && Array.getLength(result) != 0) { result = this.cloneArray(result); } return result; } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?