## 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