抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

注解

1.重复注解

自从Java 5中引入注解以来,这个特性开始变得非常流行,并在各个框架和项目中被广泛使用。不过,注解有一个很大的限制是:在同一个地方不能多次使用同一个注解。Java 8打破了这个限制,引入了重复注解的概念,允许在同一个地方多次使用同一个注解。 在Java 8中使用@Repeatable注解定义重复注解,实际上,这并不是语言层面的改进,而是编译器做的一个trick,底层的技术仍然相同。可以利用下面的代码说明:

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

package com.ehking.example.java8.newfeature.demo09;

import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


/**
* java8 重复注解测试
*/
public class RepeatAnnotations {


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Filters {
Filter[] value();
}


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Filters.class)
public @interface Filter {
String value();
}

@Filter("filter1")
@Filter("filter2")
public interface Filterable {

}

public static void main(String[] args) {
for (Filter filter : Filterable.class.getAnnotationsByType(Filter.class)) {
System.out.println(filter.value());
}
}

}

正如我们所见,这里的Filter类使用@Repeatable(Filters.class)注解修饰,而Filters是存放Filter注解的容器,编译器尽量对开发者屏蔽这些细节。这样,Filterable接口可以用两个Filter注解注释(这里并没有提到任何关于Filters的信息)。 另外,反射API提供了一个新的方法:getAnnotationsByType(),可以返回某个类型的重复注解,例如Filterable.class.getAnnoation(Filters.class)将返回两个Filter实例,输出到控制台的内容如下所示:

filter1

filter2

详细的例子看:https://unmi.cc/java8-repeatable-annotations/#more-7668

2. 类型注解

Java 8拓宽了注解的应用场景。现在,注解几乎可以使用在任何元素上:局部变量、接口类型、超类和接口实现类,甚至可以用在函数的异常定义上。比如:

1
2
3
4
5
6
7
8
9
10
11
12
13

//创建类实例
new @Interned MyObject();

//类型映射
myString = (@NonNull String) str;

//implements 语句中
class UnmodifiableList<T> implements @Readonly List<@Readonly T> { ... }

//throw exception声明
void monitorTemperature() throws @Critical TemperatureException { ... }

需要注意的是,类型注解只是语法而不是语义,并不会影响java的编译时间,加载时间,以及运行时间,也就是说,编译成class文件的时候并不包含类型注解。

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

package com.ehking.example.java8.newfeature.demo09;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Collection;


/**
* <p>
* java8 注解可以用在任何地方
*/
public class Annotations {

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
public @interface NonEmpty {

}

public static class Holder<@NonEmpty T> extends @NonEmpty Object {
public void method() throws @NonEmpty Exception {
}

}

public static void main(String[] args) {
final Holder<String> holder = new @NonEmpty Holder<String>();
@NonEmpty Collection<@NonEmpty String> strings = new ArrayList<>();
}

}

ElementType.TYPE_USER和ElementType.TYPE_PARAMETER是Java 8新增的两个注解,用于描述注解的使用场景。Java 语言也做了对应的改变,以识别这些新增的注解。

TYPE_PARAMETER:表示该注解能写在类型参数的声明语句中。类型参数声明如:
TYPE_USE:表示注解可以再任何用到类型的地方使用,比如允许在如下位置使用:

  1. 创建对象(用new关键字创建)
  2. 类型转换
  3. 使用implements实现接口
  4. 使用throws声明抛出异常