## Java 8 Annotation 新特性初体验
### 特性一:Type Annotation
在 Java 8 之前的版本中,只能允许在声明式前使用 Annotation。而在 Java 8 版本中,Annotation 可以被用在任何使用 Type 的地方,例如:初始化对象时 \(new\),对象类型转化时,使用 implements 表达式时,或者使用 throws 表达式时。
##### 清单 1. Type Annotation 使用示例
```
//初始化对象时
String myString = new @NotNull String();
//对象类型转化时
myString = (@NonNull String) str;
//使用 implements 表达式时
class MyList<T> implements @ReadOnly List<@ReadOnly T>{
...
}
//使用 throws 表达式时
public void validateValues() throws @Critical ValidationFailedException{
...
}
```
定义一个 Type Annotation 的方法与普通的 Annotation 类似,只需要指定 Target 为 ElementType.TYPE\_PARAMETER 或者 ElementType.TYPE\_USE,或者同时指定这两个 Target。
##### 清单 2. 定义 Type Annotation 示例
```
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
public @interface MyAnnotation {
}
```
ElementType.TYPE\_PARAMETER 表示这个 Annotation 可以用在 Type 的声明式前,而 ElementType.TYPE\_USE 表示这个 Annotation 可以用在所有使用 Type 的地方(如:泛型,类型转换等)
与 Java 8 之前的 Annotation 类似的是,Type Annotation 也可以通过设置 Retention 在编译后保留在 class 文件中(RetentionPolicy.CLASS)或者运行时可访问(RetentionPolicy.RUNTIME)。但是与之前不同的是,Type Annotation 有两个新的特性:在本地变量上的 Annotation 可以保留在 class 文件中,以及泛型类型可以被保留甚至在运行时被访问。
虽然 Type Annotation 可以保留在 class 文件中,但是它并不会改变程序代码本身的行为。例如在一个方法前加上 Annotation,调用此方法返回的结果和不加 Annotation 的时候一致。
Java 8 通过引入 Type Annotation,使得开发者可以在更多的地方使用 Annotation,从而能够更全面地对代码进行分析以及进行更强的类型检查。
### 特性二:Repeating Annotation
在实际应用中,可能会出现需要对同一个声明式或者类型加上相同的 Annotation(包含不同的属性值)的情况。
例如系统中除了管理员之外,还添加了超级管理员这一权限,对于某些只能由这两种角色调用的特定方法,可以使用 Repeating Annotation。
##### 清单 3. Repeating Annotation 使用示例-1
```
@Access(role="SuperAdministrator")
@Access(role="Administrator")
public void doCheck() {
......
}
```
上面的示例是针对方法使用 Annotation, 开发者也可以根据产品中的具体需求在其他地方使用 Repeating Annotation。例如某个类专门提供管理员相关的功能,可以直接在这个类上标注同样的 Annotation。
##### 清单 4. Repeating Annotation 使用示例-2
```
@Access(role="SuperAdministrator")
@Access(role="Administrator")
public class AdminServices{
}
```
之前版本的 JDK 并不允许开发者在同一个声明式前加注同样的 Annotation,(即使属性值不同)这样的代码在编译过程中会提示错误。而 Java 8 解除了这一限制,开发者可以根据各自系统中的实际需求在所有可以使用 Annotation 的地方使用 Repeating Annotation。
由于兼容性的缘故,Repeating Annotation 并不是所有新定义的 Annotation 的默认特性,需要开发者根据自己的需求决定新定义的 Annotation 是否可以重复标注。Java 编译器会自动把 Repeating Annotation 储存到指定的 Container Annotation 中。而为了触发编译器进行这一操作,开发者需要进行以下的定义:
首先,在需要重复标注特性的 Annotation 前加上 @Repeatable 标签,示例如下:
##### 清单 5. 定义 Repeating Annotation 示例
```
@Repeatable(AccessContainer.class)
public @interface Access {
String role();
}
```
@Repeatable 标签后括号中的值即为指定的 Container Annotation 的类型。在这个例子中,Container Annotation 的类型是 AccessContainer,Java 编译器会把重复的 Access 对象保存在 AccessContainer 中。
AccessContainer 中必须定义返回数组类型的 value 方法。数组中元素的类型必须为对应的 Repeating Annotation 类型。具体示例如下:
##### 清单 6. 定义 Container Annotation 示例
```
public @interface AccessContainer {
Access[] value();
}
```
可以通过 Java 的反射机制获取注解的 Annotation。一种方式是通过 AnnotatedElement 接口的 getAnnotationByType\(Class<T>\) 首先获得 Container Annotation,然后再通过 Container Annotation 的 value 方法获得 Repeating Annotation。另一种方式是用过 AnnotatedElement 接口的 getAnnotations\(Class<T>\) 方法一次性返回 Repeating Annotation。
Repeating Annotation 使得开发者可以根据具体的需求对同一个声明式或者类型加上同一类型的注解,从而增加代码的灵活性和可读性。
- java演变
- JDK各个版本的新特性
- JDK1.5新特性
- JDK1.6新特性
- JDK1.7新特性
- JDK1.8新特性
- JAVA基础
- 面向对象特性
- 多态
- 方法重载
- 方法重写
- class
- 常量
- 访问修饰符
- 类加载路径
- java-equals
- 局部类
- java-hashCode
- Java类初始化顺序
- java-clone方法
- JAVA对象实例化的方法
- 基础部分
- JAVA基础特性
- JAVA关键字
- javabean
- static
- 日期相关
- final
- interface
- 函数式接口
- JAVA异常
- 异常屏蔽
- try-with-resource资源泄露
- JAVA引用
- WeakReference
- SoftReference
- PhantomReference
- 位运算符
- try-with-resource语法糖
- JDK冷知识
- JAVA包装类
- JAVA基本类型与包装类
- java.lang.Boolean
- java.lang.Integer
- java.lang.Byte
- java.lang.Short
- java.lang.Long
- java.lang.Float
- java.lang.Double
- java.lang.Character
- 日期相关
- TemporalAdjusters
- String
- 字符串常量池
- String拼接
- String编译期优化
- StringBuilder&StringBuffer
- intern
- 注解
- java标准注解
- 内置注解
- 元注解
- 自定义注解
- 注解处理器
- JVM注解
- Java8 Annotation新特性
- 反射-Reflective
- Reflection
- Class
- Constructor
- Method
- javabean-property
- MethodHandles
- 泛型
- 类型擦除
- bridge-method
- Accessor&Mutator方法
- enum
- JAVA数组
- finalize方法
- JAR文件
- JAVA高级编程
- CORBA
- JMX
- SPI
- Java SPI使用约定
- ServiceLoader
- 实际应用
- IO
- 工具类
- JDK常用工具类
- Objects
- System
- Optional
- Throwable
- Collections
- Array
- Arrays
- System
- Unsafe
- Number
- ClassLoader
- Runtime
- Object
- Comparator
- VarHandle
- 数据结构
- 栈-Stack
- 队列(Queue)
- Deque
- PriorityQueue
- BlockingQueue
- SynchronousQueue
- ArrayBlockingQueue
- LinkedBlockingQueue
- PriorityBlockingQueue
- ConcurrentLinkedQueue
- 列表
- 迭代器
- KV键值对数据类型
- HashMap
- TreeMap
- Hash冲突
- ConcurrentHashMap
- JDK1.7 ConcurrentHashMap结构
- jdk7&jdk8区别
- 集合
- Vector
- Stack
- HashSet
- TreeSet
- ArrayList
- LinkedList
- ArrayList && LinkedList相互转换
- 线程安全的集合类
- 集合类遍历性能
- 并发容器
- CopyOnWriteArrayList
- ConcurrentHashMap
- 同步容器
- BitMap
- BloomFilter
- SkipList
- 设计模式
- 设计模式六大原则
- 单例模式
- 代理模式
- 静态代理
- 动态代理
- JDK动态代理
- cglib动态代理
- spring aop
- 策略模式
- SpringAOP策略模式的运用
- 生产者消费者模式
- 迭代器模式
- 函数式编程
- 方法引用
- 性能问题
- Lambda
- Lambda类型检查
- Stream
- findFirst和findAny
- reduce
- 原始类型流特化
- 无限流
- 收集器
- 并行流
- AOP
- 静态织入
- aspect
- aspect的定义
- AspectJ与SpringAOP
- 动态织入
- 静态代理
- 动态代理
- JDK动态代理
- CGLib动态代理
- Spring AOP
- SpringAOP五种通知类型
- @Before
- @AfterReturning
- @AfterThrowing
- @After
- @Around
- Aspect优先级
- SpringAOP切点表达式
- within
- execution
- 嵌套调用
- 系统优化与重构
- 重叠构造器模式
- 工具类构造器优化
- 常见面试题
- new Object()到底占用几个字节
- 访问修饰符
- cloneable接口实现原理
- 异常分类以及处理机制
- wait和sleep的区别
- 数组在内存中如何分配
- 类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式
- 类的实例化顺序
- 附录
- JAVA术语
- FAQ
- 墨菲定律
- 康威定律
- 软件设计原则
- 阿姆达尔定律
- 字节码工具
- OSGI