简介: 是什么, 用途, 为什么有用

Annotation 是一种元数据(metadata),它本身不是代码,但提供了一些关于代码的数据。这些数据可以是限定代码的一些功能,也可以是增加一些功能。可以将它理解为代码的修饰符,将代码当作一个名词,则Annotation是一个形容词,它使这个名词更加准确、或限定为更小的范围。如红红的苹果,直接说苹果也行,但有了红红的这个形容词,就更加准确了。 Annotation可以向编译器提供一些信息,如检测错误(@Override)、消除编译告警(@SuppressWarning)。 编译期生成代码(@Junit)。运行期提供一些检查机制(@NonNull)。被框架广泛使用。 和comment一样,annotation也能够起到描述代码功能。但它还具有检查机制。 为什么是需要的?有些信息无法通过代码表达出来,此时通过Annotation可以很好的达到。

使用: 一个简单例子,如@Override。系统提供的annotation,做成列表

Java 预定义的annotation

name description
@Deprecated 被修饰的元素已经被弃用,不应该再使用。编译器会打印一个告警,如果这个元素还被使用
@Override 被修饰元素会覆盖基类的定义。
@SuppressWarnings 消除一个编译告警。接受一个参数
@SafeVarargs 指明方法不会对varargs做不安全的操作。unchecked 告警会被抑制
@FunctionalInterface 被用作为函数式接口,java8引入

修饰其它annotation的annotation

@Retention 参数: RetentionPolicy.SOURCE, .CLASS, .RUNTIME. 表示这个annotation 会被保存的地方
@Documented 元素必须被javadoc文档化
@Target 参数:ElementType.METHOD, .ANNOTATION_TYPE, .CONSTRUCTOR, .FIELD, .LOCAL_VARIABLE,
  .PACKAGE, .PARAMETER, .TYPE. 指定元素的类型。
@Inherited 这个annotation会被它修改的类型的子类继承
@Repeatable 可被多次应用在一个元素上

REF: https://docs.oracle.com/javase/tutorial/java/annotations/predefined.html

使用方法,以@Override为例。

class A {
void foo(){
System.out.println("Supper class");
}
}
class A1 extends A {
@Override
void foo(){
System.out.println("Sub class");
}
}
class Test {
public static void main(String[] args) {
A a = new A1();
a.foo();
}
}

@Override确保被修饰方法确实是覆盖了一个基类的方法,而不是定义了一个新的方法(这种情况在方法名拼写错误时发生),或重载了一个方法(在参数类型错误时发生)。以下是一个方法名拼写错误的例子。原本想覆盖基类的foo方法,但却拼写错了,导致程序结果错误。通过@Override在编译器就可检测出来。

class A {
void foo(){
System.out.println("Supper class");
}
}
class A1 extends A {
void fooo(){
System.out.println("Sub class");
}
}
class Test {
public static void main(String[] args) {
A a = new A1();
a.foo();
}
}

定义新的annotation。 涉及到的语法, processor的编写(以及使用APT辅助编写)。

定义一个新的annotation包括两部分,annotation本身的定义,和 annotation processor的定义。 其中annotation本身的定义相当于给系统增加了一个annotaion类型。 annotation processor是来解析、处理这个annotation. 一个定义annotation的例子:

定义了一个名为Autocall的annotation,它有一个属性 msg(默认值为"")。@Rentention 说明它会在RUNTIME时使用,@Target说明它只能修饰方法。

使用这个annotaion,修饰Test的foo方法:

class Test {
@Autocall
public static foo() { }
public static void main(String[] args) {
}
}

这个annotation设计的作用是使被修饰方法自动被main函数调用。这个需要新增代码来实现,也即为这个annotation编写一个processor来实现。如果没有processor, annotation和comment没什么区别。

Annotation processor的例子:

import java.lang.annotation.*;
import java.lang.Class;
import java.lang.reflect.Method; @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Autocall {
String msg() default "";
} class AutocallProcessor {
static void process(Class cls) {
try{
Class anntCls= Class.forName("Autocall");
for(Method mtd: cls.getDeclaredMethods()){
Autocall annt = (Autocall)mtd.getDeclaredAnnotation(anntCls);
if (annt != null) {
// call this Method.
try{
mtd.invoke(null);
} catch(Exception e) {
e.printStackTrace();
}
}
}
} catch (ClassNotFoundException e){
System.out.println("ClassNotFoundException");
System.exit(1);
} }
@Autocall
static void foo(){
System.out.println("Foo called");
}
public static void main(String[] args) {
try{
process(Class.forName("AutocallProcessor"));
} catch (ClassNotFoundException e) {
e.printStackTrace(); }
}
}

在框架中的应用。如Junit中。

Junit中定义了@Test,被修饰的方法会被当作一个测试方法。

Annotation: 代码的修饰符的更多相关文章

  1. Java 基础 面向对象之关键字内部类代码块修饰符

    final final概念 继承的出现提高了代码的复用性,并方便开发.但随之也有问题,有些类在描述完之后,不想被继承,或者有些类中的部分方法功能是固定的,不想让子类重写.可是当子类继承了这些特殊类之后 ...

  2. Java修饰符关键词大全

    所以我以此主题写了这篇文章.这也是一个可用于测试你的计算机科学知识的面试问题. Java修饰符是你添加到变量.类和方法以改变其含义的关键词.它们可分为两组: 访问控制修饰符 非访问修饰符 让我们先来看 ...

  3. Java基础之数据类型、内存、修饰符、代码块

    Java 数据类型 基本数据类型 数值:int.short.long 字符:char 布尔:boolean 引用数据类型 class(类) interface(接口) 数组[] 所占字节数(1 byt ...

  4. 转: 【Java并发编程】之五:volatile变量修饰符—意料之外的问题(含代码)

    转载请注明出处:     volatile用处说明     在JDK1.2之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的.而随着JVM的成熟和优化,现在在多线程 ...

  5. java 匿名对象,内部类,修饰符,代码块

    匿名对象是在建对象时只有创建对象的语句方法而没有把对象的地址赋值给变量,匿名对象只能调用一次方法,想再调用时需要再创建一个新的匿名对象 创建普通对象:Person p =new Person(); 创 ...

  6. Java基础内部类、包的声名、访问修饰符、代码块整理

    内部类 14.1内部类概念 将类写在其他类的内部,可以写在其他类的成员位置和局部位置,这时写在其他类内部的类就称为内部类.其他类也称为外部类. 内部类分为成员内部类与局部内部类. 我们定义内部类时,就 ...

  7. [Day13]static、final、匿名对象、内部类、包、修饰符、代码块

    1.final-最终 (1)final的特点 final修饰类不可以被继承,但是可以继承其他类 final修饰的方法不可以被覆盖,但父类中没有final修饰方法,子类覆盖后可以加final final ...

  8. 13_Java面向对象_第13天(static、final、匿名对象、内部类、包、修饰符、代码块)_讲义

    今日内容介绍 1.final 关键字 2.static 关键字 3.匿名对象 4.内部类 5.包的声明与访问 6.访问修饰符 7.代码块 01final关键字概念 A: 概述 继承的出现提高了代码的复 ...

  9. 5、static、final、匿名对象、内部类、包、修饰符、代码块

    final关键字 final关键字概念 * A: 概述 继承的出现提高了代码的复用性,并方便开发.但随之也有问题,有些类在描述完之后,不想被继承, 或者有些类中的部分方法功能是固定的,不想让子类重写. ...

随机推荐

  1. CentOS7防火墙firewalld

    1.firewalld的基本使用 启动: systemctl start firewalld 查看状态: systemctl status firewalld  停止: systemctl disab ...

  2. 快压、360压缩、WinRAR关于打开快压通过超高压缩比压缩后的文件不兼容的问题

    今天接收了同事发过来的一个压缩文件,用360压缩打开和用WinRAR打开压缩文件,傻眼了,这发的是什么鬼压缩包.压缩包的文件大小有27533KB,用360压缩工具解压查看只有121.5kb,而且完全没 ...

  3. JVM虚拟机—JVM的垃圾回收机制(转载)

    1.前言 理解JVM的垃圾回收机制(简称GC)有什么好处呢?作为一名软件开发者,满足自己的好奇心将是一个很好的理由,不过更重要的是,理解GC工作机制可以帮助你写出更好的Java程序. 在学习GC前,你 ...

  4. corethink功能模块探索开发(十七)opencmf.php 配置文件

    图样: opencmf.php存在于每个模块的根目录,是模块配置文件. 能进行持久化配置参数保存,一开始我以为是写文件或者做缓存,后来在数据库中发现admin_module表,存储了每个模块的配置参数 ...

  5. C++异常安全、copy and swap

    异常安全的代码是指,满足两个条件 1异常中立性 : 是指当你的代码(包括你调用的代码)引发异常时,这个异常 能保持原样传递到外层调用代码.(异常中立,就是指任何底层的异常都会抛出到上层,也就相当于是异 ...

  6. numpy.random.seed()

    numpy.random.seed():用于指定随机数生成时使用算法的开始值,如果没有指定每次生成的值都不一样 如果不指定seed的值,那么每次随机生成的数字都不一样: In [17]: import ...

  7. mongo常用查询

    复杂查询: and: or: lte,gte,=: and+lt:  , 逗号表示and, $lt小于写在值当中 查询实例: 找到含有指定数据文档 查找条件spcode有1个字符长度的文档 db.sp ...

  8. python全栈开发之OS模块的总结

    OS模块 1. os.name()      获取当前的系统 2.os.getcwd      #获取当前的工作目录 import os cwd=os.getcwd() # dir=os.listdi ...

  9. bat脚本相关

    前期准备: 将要执行的脚本名字生成到一个txt文件 首先进入dos运行程序的目录下:输入dir *.jmx /B>FileScript.txt 采用dir *.jmx>list.txt 如 ...

  10. 利用cgroup控制进程使用的资源(cpu、内存等)

    实验环境:centos 6.10 1.安装libcgroup yum install -y libcgroup 2.进入资源控制器默认挂载目录/cgroup [root@hadoop1 cgroup] ...