2016-10-10 54 views
5

我不明白的下面的代碼的行爲: https://gist.github.com/tomaszalusky/3e3777b4fd0c6096f3f707bb19b50b52 - 見嵌入式:對於嵌套類型,爲什麼對泛型類型參數的註釋不可見?

import java.lang.reflect.*; 
import java.util.*; 
import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 


public class AnnotationOnTypeArgument { 

    @Target({ElementType.FIELD,ElementType.PARAMETER,ElementType.METHOD,ElementType.TYPE_USE}) 
    @Retention(RetentionPolicy.RUNTIME) 
    public @interface Anno { 

    } 

    interface Nested<T> { 

    } 

    Toplevel<@Anno Integer> toplevel; 

    Nested<@Anno Integer> nested; 

    public static void main(String[] args) throws Exception { 
     print(AnnotationOnTypeArgument.class.getDeclaredField("toplevel")); 
     print(AnnotationOnTypeArgument.class.getDeclaredField("nested")); 
    } 

    private static void print(Field field) { 
     AnnotatedType annotatedType = field.getAnnotatedType(); 
     AnnotatedParameterizedType annotatedParameterizedType = (AnnotatedParameterizedType)annotatedType; 
     ParameterizedType parameterizedType = (ParameterizedType)annotatedParameterizedType.getType(); 
     AnnotatedType argType = annotatedParameterizedType.getAnnotatedActualTypeArguments()[0]; 
     System.out.printf("field %s%ntype=%s%nannotatedType=%s%nannotations=%s%ntype=%s%n%n", 
       field.getName(), parameterizedType, argType, Arrays.asList(argType.getDeclaredAnnotations()), argType.getType()); 
    } 

} 

interface Toplevel<T> { 

} 

編輯:實際的結果是:

field toplevel 
type=Toplevel<java.lang.Integer> 
annotatedType=su[email protected]1540e19d 
annotations=[@AnnotationOnTypeArgument$Anno()] 
type=class java.lang.Integer 

field nested 
type=AnnotationOnTypeArgument.AnnotationOnTypeArgument$Nested<java.lang.Integer> 
annotatedType=su[email protected]677327b6 
annotations=[] 
type=class java.lang.Integer 

爲什麼宣佈註釋對類型參數的數組周圍類型嵌套時爲空?我希望有一個元素,就像頂級類型一樣。我很感謝任何基於JLS的解釋。

在JDK8u101(http://compilejava.net),較老的JDK8和Eclipse中一致發生。

謝謝!

回答

5

我給一些時間來調試和annotatedParameterizedType變量似乎仍包含嵌套的情況下,在其allOnSameTargetTypeAnnotations領域的參考安諾註解太

annotatedParameterizedType = {[email protected]} 
type = {[email protected]} "com.sample.Toplevel<java.lang.Integer>" 
decl = {[email protected]} "com.sample.Toplevel com.sample.AnnotationOnTypeArgument.toplevel" 
location = {[email protected]} 
    depth = 0 
    locations = {TypeAnnotation$LocationInfo$Location[0]@549} 
allOnSameTargetTypeAnnotations = {TypeAnnotation[1]@544} 
    0 = {[email protected]} "@com.sample.AnnotationOnTypeArgument$Anno() with Targetnfo: FIELD: -2, -2 on base declaration: com.sample.Toplevel com.sample.AnnotationOnTypeArgument.toplevel" 
annotations = {[email protected]} size = 0 

VS

annotatedParameterizedType = {[email protected]} 
type = {[email protected]} "com.sample.AnnotationOnTypeArgument.com.sample.AnnotationOnTypeArgument$Nested<java.lang.Integer>" 
decl = {[email protected]} "com.sample.AnnotationOnTypeArgument$Nested com.sample.AnnotationOnTypeArgument.nested" 
location = {[email protected]} 
    depth = 1 
    locations = {TypeAnnotation$LocationInfo$Location[1]@611} 
allOnSameTargetTypeAnnotations = {TypeAnnotation[1]@607} 
    0 = {[email protected]} "@com.sample.AnnotationOnTypeArgument$Anno() with Targetnfo: FIELD: -2, -2 on base declaration: com.sample.AnnotationOnTypeArgument$Nested com.sample.AnnotationOnTypeArgument.nested" 
annotations = {[email protected]} size = 0 

然而,有是位置深度的差異,即將到來的AnnotatedTypeFactory的getAnnotatedActualTypeArguments()方法包含TypeAnnotation.isSameLocationInfo()比較,作爲將註釋添加到註釋的前提條件地圖,這將成爲在嵌套的情況下,因此最終沒有添加任何元素

我沒有找到它的任何文檔。也許你在這裏發現了一個問題

+2

我認爲,我們可以追蹤它回到['AnnotatedTypeFactory' ,第105行](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/sun/reflect/annotation/AnnotatedTypeFactory.java#105)嵌套參數化類型是無條件地視爲(非'靜態')內部類(不同於可定義類型,前面7行)。實際上,詢問一個'ParametertrizedType'是否是'static',不是直接的... – Holger

4

這是OpenJDK中的一個錯誤,我前面已經報道過,我希望它能夠修復。類型註釋在實踐中並沒有真正使用過,它似乎並不是一個優先事項。正如霍爾格所說,這是在執行AnnotatedTypeFactory時的混淆。

您可以使用Byte Buddy其正確解析類文件元數據:

public static void main(String[] args) throws Exception { 

    TypeDescription type = TypePool.Default.ofClassPath() 
     .describe(AnnotationOnTypeArgument.class.getName()) 
     .resolve(); 

    print(type.getDeclaredFields().filter(named("toplevel")).getOnly()); 
    print(type.getDeclaredFields().filter(named("nested")).getOnly()); 
} 

private static void print(FieldDescription field) { 
    System.out.printf("field %s%ntype=%s%nannotations=%s%ntype=%s%n%n", 
      field.getName(), 
      field.getType(), 
      field.getType().getTypeArguments().get(0), 
      field.getType().getTypeArguments().get(0).getDeclaredAnnotations()); 
} 

這給了你所期望的輸出:

field toplevel 
type=net.bytebuddy.Toplevel<java.lang.Integer> 
annotations=class java.lang.Integer 
type=[@net.bytebuddy.AnnotationOnTypeArgument$Anno()] 

field nested 
type=net.bytebuddy.AnnotationOnTypeArgument.net.bytebuddy.AnnotationOnTypeArgument$Nested<java.lang.Integer> 
annotations=class java.lang.Integer 
type=[@net.bytebuddy.AnnotationOnTypeArgument$Anno()] 
+0

Rafael,你的意思是這個錯誤之前並不知道?你能指定報告錯誤的URL嗎? Oracle bug數據庫搜索引擎目前似乎有些不健康。 –

+1

我試圖找到它,但我不能。我通過網絡表單報告,所以我的名字不在這個問題上。我報告了大約20個與類型註釋有關的錯誤,所以它很平凡,很抱歉。不幸的是,他們很有車。這份報告現在應該大約一歲。 –

+1

嗨拉斐爾,你可以請嘗試再次找到錯誤報告?我想弄清楚我是否應該爲[類似問題]提交報告(http://stackoverflow.com/questions/42512701/type-use-annotations-get-lost-when-type-is-nested-generic -接口)。 – Tillerino

相關問題