Annotation

Posted chhhh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Annotation相关的知识,希望对你有一定的参考价值。

Annotation (注解) 表示的是能够添加到Java源代码的语法元数据。类、方法、变量、参数、包都可以被注解,可用来将信息元数据和程序元素进行关联。

Annotation 被称为注解,在Java开发中是相当常见的,通过注解,我们可以简化代码提高开发效率。例如Override Annotation,这个应该算是在开发过程中使用最多的注解了。

Annotation的作用可以分为三种:

a.标记作用,用于告诉编译器一些信息

b.编译时动态处理,如动态生成代码

c.运行时动态处理,如得到注解信息

这三个作用对应着后面自定义Annotation时说的@Retention三种值分别表示的Annotation

2.2 实现原理

Annotation分为三种:

a.标准 Annotation

包括 Override, Deprecated, SuppressWarnings,标准 Annotation 是指 Java 自带的几个 Annotation,上面三个分别表示重写函数,不鼓励使用(有更好方式、使用有风险或已不在维护)SuppressWarnings来忽略某项 Warning

b.元 Annotation

@Retention, @Target, @Inherited, @Documented,元 Annotation 是指用来定义 Annotation 的 Annotation。

—@Documented:是否会保存到 Javadoc 文档中

—@Retention:保留时间,可选值 SOURCE(源码时),CLASS(编译时),RUNTIME(运行时),默认为 CLASS,值为 SOURCE 大都为 Mark Annotation,这类 Annotation 大都用来校验,比如 Override, Deprecated, SuppressWarnings

—@Target:可以用来修饰哪些程序元素,如 TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER 等,未标注则表示可修饰所有。

—@Inherited: 是否可以被继承,默认为 false

c.自定义 Annotation

自定义 Annotation 表示自己根据需要定义的 Annotation,定义时需要用到上面的元 Annotation,这里只是一种分类而已,也可以根据作用域分为源码时、编译时、运行时 Annotation。

Annotation的框架如下:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
  
public class Main {
    public void TestJDBC(){
        //将配置文件变成输入流
        InputStream in = getClass().getClassLoader().getResourceAsStream("jdbc.properties");
        Properties properties = new Properties();
        try {
            //从流中获取配置信息到Properties对象
            properties.load(in);
            //读取配置文件
            String driverClass = properties.getProperty("driver");
            String jdbcUrl = properties.getProperty("jdbcUrl");
            String user = properties.getProperty("user");
            String password = properties.getProperty("password");
            //注册驱动
            Driver driver = (Driver)Class.forName(driverClass).newInstance();
            Connection conn = DriverManager.getConnection(jdbcUrl,user,password);
            System.out.println(conn);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
     
    public static void main(String[] args) {
        Main m = new Main();
        m.TestJDBC2();
    }
  
}

从中,我们可以看出:

(01) 1个Annotation 和 1个RetentionPolicy关联。

可以理解为:每1个Annotation对象,都会有唯一的RetentionPolicy属性。

(02) 1个Annotation 和 1~n个ElementType关联。

可以理解为:对于每1个Annotation对象,可以有若干个ElementType属性。

(03) Annotation 有许多实现类,包括:Deprecated, Documented, Inherited, Override等等。

Annotation 的每一个实现类,都“和1个RetentionPolicy关联”并且“和1~n个ElementType关联”。

Annotation定义的语法如下:

1
2
3
4
5
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation1 {
}

说明:

上面的作用是定义一个Annotation,它的名字是MyAnnotation1。定义了MyAnnotation1之后,我们可以在代码中通过“@MyAnnotation1”来使用它。

其它的,@Documented, @Target, @Retention, @interface都是来修饰MyAnnotation1的。下面分别说说它们的含义:

(01) @interface

使用@interface定义注解时,意味着它实现了java.lang.annotation.Annotation接口,即该注解就是一个Annotation。

定义Annotation时,@interface是必须的。

注意:它和我们通常的implemented实现接口的方法不同。Annotation接口的实现细节都由编译器完成。通过@interface定义注解后,该注解不能继承其他的注解或接口。

(02) @Documented

类和方法的Annotation在缺省情况下是不出现在javadoc中的。如果使用@Documented修饰该Annotation,则表示它可以出现在javadoc中。

定义Annotation时,@Documented可有可无;若没有定义,则Annotation不会出现在javadoc中。

(03) @Target(ElementType.TYPE)

前面我们说过,ElementType 是Annotation的类型属性。而@Target的作用,就是来指定Annotation的类型属性。

@Target(ElementType.TYPE) 的意思就是指定该Annotation的类型是ElementType.TYPE。这就意味着,MyAnnotation1是来修饰“类、接口(包括注释类型)或枚举声明”的注解。

定义Annotation时,@Target可有可无。若有@Target,则该Annotation只能用于它所指定的地方;若没有@Target,则该Annotation可以用于任何地方。

(04) @Retention(RetentionPolicy.RUNTIME)

前面我们说过,RetentionPolicy 是Annotation的策略属性,而@Retention的作用,就是指定Annotation的策略属性。

@Retention(RetentionPolicy.RUNTIME) 的意思就是指定该Annotation的策略是RetentionPolicy.RUNTIME。这就意味着,编译器会将该Annotation信息保留在.class文件中,并且能被虚拟机读取。

定义Annotation时,@Retention可有可无。若没有@Retention,则默认是RetentionPolicy.CLASS。

当Java源代码被编译时,编译器的一个插件annotation处理器则会处理这些annotation。处理器可以产生报告信息,或者创建附加的Java源文件或资源。如果annotation本身被加上了RententionPolicy的运行时类,则Java编译器则会将annotation的元数据存储到class文件中。然后,Java虚拟机或其他的程序可以查找这些元数据并做相应的处理。

当然除了annotation处理器可以处理annotation外,我们也可以使用反射自己来处理annotation。Java SE 5有一个名为AnnotatedElement的接口,Java的反射对象类Class,Constructor,Field,Method以及Package都实现了这个接口。这个接口用来表示当前运行在Java虚拟机中的被加上了annotation的程序元素。通过这个接口可以使用反射读取annotation。AnnotatedElement接口可以访问被加上RUNTIME标记的annotation,相应的方法有getAnnotation,getAnnotations,isAnnotationPresent。由于Annotation类型被编译和存储在二进制文件中就像class一样,所以可以像查询普通的Java对象一样查询这些方法返回的Annotation。

2.3 应用场景

Annotation被广泛用于各种框架和库中Junit/Spring/Hibernate等。

 

转自:https://www.2cto.com/kf/201708/665618.html

以上是关于Annotation的主要内容,如果未能解决你的问题,请参考以下文章

注释的基本使用与文档注释的特殊功能

Annotation 使用备忘

歌曲图像可以更快吗?

annotation

编译时处理Annotation 的一份代码

Annotation