swiftR

注解为程序提供元数据(metadata).元数据又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息。它不会影响程序的编译方式,也不会影响最终的编译结果。

注解可以提供更大的便捷性,易于维护修改,但耦合度高,而 XML 相对于注解则是相反的。

注解使用场景如下

1
2
3
编译器信息
编译时和部署时的处理
运行时处理

注解格式

1
2
@SuppressWarnings(value = "unchecked")
void myMethod() { ... }

注解使用场景

  • 类实例创建

    1
    new @annotation myobject()
  • 类型投射

    1
    myString = (@NonNull String) str;
  • 实现条款

    1
    2
    class UnmodifiableList<T> implements
    @Readonly List<@Readonly T> { ... }
  • 抛出异常声明

    1
    void testfunc() throws @annotation exception{}

注解的声明

一个简单的注解声明

1
2
3
4
@interface anno{
String name();
Interger age() default 18;
}

注解的声明,就像在 interface 声明前面添加一个@字符(@是AT,即 Annotation Type)。注解类型,其实是接口的一种特殊形式

使用注解

使用时,填充注解的值就好了

1
2
3
4
5
6
7
@anno(
name="swiftr",
age=18,
)
class testclass{

}

注解应用于其他注解

注解应用于其他注解称为元注解
java.lang.annotation中也定义了很多元注解
upload successful
@Retention 注解指定了标记的注解如何存储

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*保留在源码级,在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override、@SuppressWarnings都属于这类注解
*/
SOURCE,

/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.该标记注释是由编译器在编译时保留, 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。
*/
CLASS,

/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*该标记注解由JVM保留,因此可以使用在运行时环境。因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}

@Target 用于标记其他注解,限制什么样的 Java 元素的注解可以应用到

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
/** Class, interface (including annotation type), or enum declaration */
TYPE,

/** Field declaration (includes enum constants) */
FIELD,

/** Method declaration */
METHOD,

/** Formal parameter declaration */
PARAMETER,

/** Constructor declaration */
CONSTRUCTOR,

/** Local variable declaration */
LOCAL_VARIABLE,

/** Annotation type declaration */
ANNOTATION_TYPE,

/** Package declaration */
PACKAGE,

/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,

/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE

@Inherited 指示注释类型可以从超类继承。(默认不是 true)。当用户查询注释类型,类没有这种类型注释,此时从这个类的父类中查询注释类型。这个注释只适用于类的声明。

@Repeatable注解,在 Java SE 8 中引入的,表示该标记的注解可以多次应用到同一声明或类型使用。

类型注解

例如,确保在你的程序中一个特定变量从未被分配到 null可以这样写

1
@NotNull String str;

重复注解

注解包含相同的类型,则被称为重复注解

重复的注释被存储在一个由 Java 编译器自动产生的容器注解(container annotation)里。为了使编译器要做到这一点,你的代码里两个声明都需要。

1
2
3
@Schedule(dayOfMonth="last")
@Schedule(dayOfWeek="Fri", hour="23")
public void doPeriodicCleanup() { ... }

声明一个重复注解

1
2
3
4
5
6
@Repeatable(Schedules.class)
public @interface Schedule {
String dayOfMonth() default "first";
String dayOfWeek() default "Mon";
int hour() default 12;
}

@Repeatable的值是由java编译器生生成储存重复注解的容器

声明容器注解类型

1
2
3
public @interface Schedules {
Schedule[] value();
}

该注解的值为重复注解的数组类型

示例

下面是注解一个简单的应用

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
public class classtest {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
AnnotationTest test = new AnnotationTest();
test.execute();
//获取Annotation 的class实例
Class<AnnotationTest> cl = AnnotationTest.class;

//获取Method实例
Method method = cl.getMethod("execute",new Class[]{});

//判断是否包含myAnnotation注解
if (method.isAnnotationPresent(myAnnotation.class)){
//获取改方法注解实例
myAnnotation my = method.getAnnotation(myAnnotation.class);
//执行该方法
method.invoke(test,new Object[]{});
//获取注解的属性值
String name = my.name();
System.out.println(name);
}
//获取方法上的所有注解
Annotation[] annotations = method.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}


@Documented
@Retention(RetentionPolicy.RUNTIME)
@interface myAnnotation{
String name() default "swiftr";
}

class AnnotationTest {

@myAnnotation(name = "https://swiftr.top")
public void execute() {
System.out.println("do something~");
}
}

运行结果

1
2
3
4
5
6
do something~
do something~
https://swiftr.top
@cn.lzl.mqdemo.mianshi.注解.myAnnotation(name=https://swiftr.top)

Process finished with exit code 0