Java 8引入了Lambda Expressions和Type Annotations。註釋Lambda表達式的功能接口
隨着類型的註釋,就可以定義諸如Java註解如下:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface MyTypeAnnotation {
public String value();
}
之一,那麼可以使用此批註像如任何類型的引用:
Consumer<String> consumer = new @MyTypeAnnotation("Hello ") Consumer<String>() {
@Override
public void accept(String str) {
System.out.println(str);
}
};
下面是一個完整例如,使用此註釋打印「Hello World」:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedType;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class Java8Example {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface MyTypeAnnotation {
public String value();
}
public static void main(String[] args) {
List<String> list = Arrays.asList("World!", "Type Annotations!");
testTypeAnnotation(list, new @MyTypeAnnotation("Hello ") Consumer<String>() {
@Override
public void accept(String str) {
System.out.println(str);
}
});
}
public static void testTypeAnnotation(List<String> list, Consumer<String> consumer){
MyTypeAnnotation annotation = null;
for (AnnotatedType t : consumer.getClass().getAnnotatedInterfaces()) {
annotation = t.getAnnotation(MyTypeAnnotation.class);
if (annotation != null) {
break;
}
}
for (String str : list) {
if (annotation != null) {
System.out.print(annotation.value());
}
consumer.accept(str);
}
}
}
o安輸出將是:
Hello World!
Hello Type Annotations!
在Java 8一個也可以用lambda表達式替換匿名類在這個例子中:
public static void main(String[] args) {
List<String> list = Arrays.asList("World!", "Type Annotations!");
testTypeAnnotation(list, p -> System.out.println(p));
}
但由於編譯器推斷消費者類型參數爲λ表達式,一個不再能夠註釋所創建的消費者實例:
testTypeAnnotation(list, @MyTypeAnnotation("Hello ") (p -> System.out.println(p))); // Illegal!
人們可以投lambda表達式到消費者,然後註釋CA的類型參考ST表達:
testTypeAnnotation(list,(@MyTypeAnnotation("Hello ") Consumer<String>) (p -> System.out.println(p))); // Legal!
但這不會產生期望的結果,因爲創建Consumer類不會投表達的註解。輸出:
World!
Type Annotations!
兩個問題:
有什麼辦法來標註類似標註相應的匿名類lambda表達式,所以一得到預期的「Hello World」輸出在上面的例子?
在這個例子中,我確實投了lambda表達式並註釋了鑄造類型:有沒有什麼辦法在運行時接收這個註解實例,或者這樣的註解總是隱式地限制到RetentionPolicy.SOURCE?
這些示例已經用javac和Eclipse編譯器進行了測試。
更新
我試圖建議從@assylias,註釋而不是參數,產生一個有趣的結果。這裏是更新的測試方法:
public static void testTypeAnnotation(List<String> list, Consumer<String> consumer){
MyTypeAnnotation annotation = null;
for (AnnotatedType t : consumer.getClass().getAnnotatedInterfaces()) {
annotation = t.getAnnotation(MyTypeAnnotation.class);
if (annotation != null) {
break;
}
}
if (annotation == null) {
// search for annotated parameter instead
loop: for (Method method : consumer.getClass().getMethods()) {
for (AnnotatedType t : method.getAnnotatedParameterTypes()) {
annotation = t.getAnnotation(MyTypeAnnotation.class);
if (annotation != null) {
break loop;
}
}
}
}
for (String str : list) {
if (annotation != null) {
System.out.print(annotation.value());
}
consumer.accept(str);
}
}
現在,人們也可以產生「Hello World」的結果,標註匿名類的參數時:
public static void main(String[] args) {
List<String> list = Arrays.asList("World!", "Type Annotations!");
testTypeAnnotation(list, new Consumer<String>() {
@Override
public void accept(@MyTypeAnnotation("Hello ") String str) {
System.out.println(str);
}
});
}
但標註的參數不不lambda表達式工作:
public static void main(String[] args) {
List<String> list = Arrays.asList("World!", "Type Annotations!");
testTypeAnnotation(list, (@MyTypeAnnotation("Hello ") String str) -> System.out.println(str));
}
有趣的是,它也不可能接收參數的名稱(當compil在使用lambda表達式時使用javac -parameter)。我不確定,如果這種行爲是有意的,如果lambda參數註釋尚未實現,或者這應該被視爲編譯器的錯誤。
您也可以嘗試'(@MyTypeAnnotation( 「你好」)的String) - >的System.out.println(S)'我雖然沒有設法訪問註釋值... – assylias
@assylias感謝您的輸入 - 好主意。我做了一些帶有註釋參數的測試,並將結果添加到我的問題的更新部分。 – Balder
@assylias更新:無法接收類型註釋的lambda表達式的形式參數,如在您的示例中,最有可能與[JDK bug 8027181](https://bugs.openjdk.java.net/瀏覽/ JDK-8027181)和[Eclipse bug 430571](https://bugs.eclipse.org/bugs/show_bug.cgi?id=430571)。 – Balder