blog
  • 吕系小的博客
  • Java
    • 读书笔记
      • Thinking in Java
        • Object
          • 面向对象
          • 对象的创建与生命周期
          • 对象与基本类型的存储位置
        • 控制流程
          • 实现类似goto的操作
        • 初始化与清理
          • 对象的创建过程
          • 垃圾回收器如何工作
          • JIT
        • 复用类
          • 继承与初始化
          • final关键字
        • 多态
          • 构造器和多态
          • 方法和调用绑定
      • Java核心技术卷1
        • 面向对象
        • Unicode和char类型
        • Object:所有类的超类
        • 理解方法调用
        • 代理
        • lambda
        • 接口
        • 异常
        • 并发
          • 线程
          • volatile
          • 阻塞队列
          • 线程安全的集合
          • Callable与Future
          • 同步
          • 执行器
      • Java核心技术卷2
        • 流库
          • 流
          • 并行流
          • 基本类型流
          • 约简操作
          • 群组、分区、下游收集器
          • 收集结果
          • Optional
        • IO
          • 输入、输出流
          • 组合流过滤器
          • 文本输入与输出
          • 字符编码方式
          • 读写二进制数据
          • 随机访问文件
          • 对象输入、输出流与序列化
          • Path
          • 目录
          • 内存映射文件
          • Files
        • 日期和时间
          • 时间线
          • 本地时间
          • 日期调整期
          • 时区时间
          • 格式化和解析
        • 脚本、编译与注解处理
          • 脚本
          • 编译器
          • 注解
          • 标准注解
          • 源码级注解处理
        • 安全
          • 类加载器
          • 安全管理器与访问权限
          • 数字签名
      • 深入理解Java虚拟机
        • Java内存区域
        • 垃圾收集机制
      • Head First Java
        • Chapter1.Breaking the Sur face
        • Chapter2.A Trip to Objectville.There will be objects.
        • Chapter3.Know Your Variables
        • Chapter4.How Objects Behave
        • Chapter7.Better Living in Objectville
        • Chapter9.constructors and garbage collection
        • Chapter10.statics
      • 深入分析JavaWeb技术内幕
        • 深入web请求过程
        • 深入分析JavaIO的工作机制
      • Spring IN ACTION
        • Spring之旅
          • 依赖注入
          • IOC 容器
        • 装配bean
          • 组件扫描与自动装配
          • 通过Java代码装配bean
        • 高级装配
          • profile
          • 条件化bean
          • 处理自动装配的歧义性
          • bean的作用域
          • Environment
          • 属性占位符
    • 前后端那些事
      • 跨域访问
      • Token验证机制
    • 学习笔记
  • 数据库
    • MySQL
      • 基础篇
        • SQL分类及帮助文档
        • MySQL架构
        • 存储引擎
        • MySQL支持的数据类型
        • 数据类型的选择
        • 常用函数
      • 索引篇
        • 索引
      • 事务篇
      • 实际问题
        • 成绩分组取最大值问题
  • 计算机操作系统
    • 计算机操作系统组成与分类
    • 进程
      • 进程
      • 进程管理
      • 多线程结构进程
      • KLT与ULK
      • 处理器调度
    • 存储管理
      • 存储管理的主要模式
      • 存储管理的功能
      • 虚拟存储器的概念
      • 存储器的硬件支撑
      • 页式存储管理的基本原理
      • 页式虚拟存储管理
      • 页面调度
      • 反置页表
      • 段式存储管理
      • 段式虚拟存储
      • 段页式存储管理
    • 设备管理
      • IO缓冲区
    • 文件管理
      • 文件的存储
      • 文件的逻辑结构
      • 文件的物理结构
Powered by GitBook
On this page
  1. Java
  2. 读书笔记
  3. Java核心技术卷2
  4. 脚本、编译与注解处理

注解

注解

注解是那些插入到源代码中使用其他工具可以对其进行处理的标签。

注解不会改变程序的编译方式。Java编译器对于包含注解和不包含注解的代码会生成相同的虚拟机指令。

注解简介

在Java中,注解是当作一个修饰符来使用的,它被置于被注解项之前,中间没有分号。每一个注解的名称前面都加上了@符号,注解是代码的一部分。

注解可以出现的地方

  • 包

  • 类(包括enum)

  • 接口(包括注解接口)

  • 方法

  • 构造器

  • 实例域(包含enum常量)

  • 局部变量

  • 参数变量

  • 类型参数

对局部变量的注解只能在源码级别上进行处理。类文件并不描述局部变量。因此,所有的局部变量注解在编译完一个类的时候就会被遗弃掉。同样地,对包的注解不能在源码级别之外存在。

每个注解都必须通过一个注解接口进行定义。这些接口中的方法与注解中的元素相对应。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test(){
    long timeout() default 0L;
}

@interface声明创建了一个真正的Java接口。处理注解的工具将接收那些实现了这个注解接口的对象。这类工具可以调用timeout方法来检索某个特定Test注解的timeout元素。

注解Target和Retention是元注解。它们是注解了Test注解,即将Test注解标识成一个只能运用到方法上的注解,并且当类文件载入到虚拟机的时候,仍可以保留下来。

注解语法

注解是由注解接口定义的

modifiers @interface AnnotationName {
    elementDeclaration1
    elementDeclaration2
}

每个元素声明都具有下面这种形式

type elementName();

或者

type elementName() default value;

例子如下:

public @interfcace BugReport{
    String assignedTo() default "[none]";
    int severity();
}

所有的注解接口都隐式地扩展自java.lang.annotation.Annotation接口。这个接口是一个常规接口,不是一个注解接口。

注解元素的类型

  • 基本类型

  • String

  • Class(具有一个可选的类型参数,例如Class<? extends MyClass>)

  • enum类型

  • 注解类型

  • 由前面所述类型组成的数组(由数组组成的数组不是合法的元素类型)

例子

public @interface BugReport{
    enum Statis{ UNCONFIRMED,CONFIRMED,FIXED,NOTABUG};
    boolean showStopper() default false;
    String assignedTo() default "[none]";
    Class<?> testCase() default Void.class;
    Status status() default Status.UNCONFIRMED;
    Reference ref() default @Reference(); //an annotation type
    String[] reportedBy();
}

默认值并不是和注解存储在一起的;相反地,它们是动态计算而来的。例如,如果你将元素assignedTo的默认值更改为"[]",然后重新编译BugReport接口,那么注解@BugRePORT(serverity=10)将使用这个新的默认值,甚至在那些在默认值修改之前就已经编译过的类文件中也是如此。

注解是由编译器计算而来的,因此,所有元素值必须是编译器常量。

一个注解元素永远不能设置为null,甚至不允许其默认值为null。

单值注解

如果一个元素具有特殊的名字value,并且没有指定其他元素,那么你就可以忽略掉这个元素名以及等号。

public @interface ActionListenerFor{
    String value();
}

我们可以将这个注解书写成如下形式

@ActionListenerFor("yellowButton")

注解类型用法

类型用法注解可以放置到类型引元之前

  • 与泛化类型引元一起使用:List<@NonNull String>,Comparator.<@NonNull String> reverseOrder().

  • 数组中的任何位置: @NonNull String[][] words(words[i][j]部位null),String @NonNull [][] words(words不为null),String[] @NonNull [] words(words[i]不为null)。

  • 与超累和实现接口一起使用:class Warning extends @Localized Message

  • 与构造器调用一起使用:new @Localized String(...)

  • 与强制转型和instanceof检查一起使用:(@Localized String) text,if(text instanceof @Localized String)。(这些注解只供外部工具使用,它们对强制转型和instanceof检查不会产生任何影响)

  • 与异常规约一起使用:public String read() throws @Localized IOException

  • 与通配符和类型边界一起使用:List<@Localized ? extends Message>, List<? extends @Localized Message>

  • 与方法和构造器引用一起使用:@Localized Message::getText

注解this

假设想要将参数注解为在方法中不会被修改。

public class Point{
    public boolean equals(@ReadOnly Object other){...}
}

那么,处理这个注解的工具在看到下面的调用时

p.equals(q)

就会推理出q没有被修改过。

但是p呢?

当该方法被调用时,this变量是绑定到p的。虽然this从来都没有被声明过,但是你可以用下面的方法来声明它

public class Point{
    public boolean equals(@ReadOnly Point this,@ReadOnly Object other){...}
}

第一个参数被称为接收器参数,它必须被命名为this,而它的类型就是要构建的类。

你只能为方法而不能为构造器提供接收器参数。从概念上讲,构造器中的this引用在构造器没有执行完之前还不是给定类型的对象。所以,放置在构造器上的注解描述的是被构建的对象的属性。

Previous编译器Next标准注解

Last updated 6 years ago