【JDK8】Annotation 功能增強
|
在 JDK8 出現之前, JDK8 的 public class MailBox<@Email T> {
...
}
那麼,你在定義 package cc.openhome;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Target(ElementType.TYPE_PARAMETER)
public @interface Email {}
package cc.openhome;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Target(ElementType.TYPE_USE)
public @interface Test {}
那以下幾個標註範例都是可以的: List<@Test Comparable> list1 = new ArrayList<>(); List<? extends Comparable> list2 = new ArrayList<@Test Comparable>(); @Test String text; text = (@Test String) new Object(); java.util. @Test Scanner console; console = new java. util. @Test11 Scanner(System.in); 注意,這幾個範例都僅對 @Test java.lang.String text; 上面這個例子中, 可以在更多地方標註,一些靜態分析工具或框架是最主要受到影響的對象,舉例來說,The Checker Framework 中有個 ...
@Retention(value=RUNTIME)
@Target(value={TYPE_USE,TYPE_PARAMETER})
public @interface NonNull
...
你可以 下載 The Checker Framework,撰寫本文的時間點它是 1.8.1 版,下載完成後解開 zip 檔案,並設置環境變數:
最主要的是,你的 package cc.openhome;
import org.checkerframework.checker.nullness.qual.*;
public class GetStarted {
public static void main() {
java.util.@NonNull List<String> elems =
new java.util.ArrayList<>();
}
}
這個簡單的程式使用了
程式中的 java.util.@NonNull List<String> elems = null; 使用相同指令編譯時,就會發生以下編譯錯誤: error: [assignment.type.incompatible] incompatible types in assignment.
java.util.@NonNull List<String> elems = null;
^
found : null
required: @UnknownInitialization @NonNull List<@Initialized @NonNull String>
1 error
可以看到,對於 package cc.openhome;
import org.checkerframework.checker.nullness.qual.*;
import java.util.*;
public class GetStarted {
public static void main(String[] args) {
List<String> elems = new ArrayList<>();
elems.add(null);
}
}
使用相同指令編譯,預設會檢查出被加入 error: [argument.type.incompatible] incompatible types in argument.
elems.add(null);
^
found : null
required: @Initialized @NonNull String
1 error
如果你真的想允許 List<@Nullable String> elems = new ArrayList<>(); elems.add(null); 想要知道更多 Checker 的使用,可以參考The Checker Framework Manual。 JDK8 除了 public @interface Filter {
String[] value();
}
這可以讓你如下進行標註: @Filter({"/admin", "/manager"})
public interface SecurityFilter {
...
}
如果你想要另一種如下的標註風格: package cc.openhome;
@Filter("/admin")
@Filter("/manager")
public interface SecurityFilter {}
在 JDK8 還沒出現之前,沒有辦法達到這點需求,如果使用 JDK8,可以如下定義 package cc.openhome;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Filters.class)
public @interface Filter {
String value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface Filters {
Filter[] value();
}
實際上這是編譯器的把戲,在這邊你使用 JDK8 在 package cc.openhome;
import static java.lang.System.out;
public class SecurityTool {
public static void main(String[] args) {
Filter[] filters = SecurityFilter.class.
getAnnotationsByType(Filter.class);
for(Filter filter : filters) {
out.println(filter.value());
}
out.println(SecurityFilter.class.getAnnotation(Filter.class));
}
}
執行結果如下,可以觀察到,對於被標註為 /admin /manager null |

Java 學習之路





