2016-10-10 1 views
5

I: https://gist.github.com/tomaszalusky/3e3777b4fd0c6096f3f707bb19b50b52 - siehe eingebettet:Warum Anmerkung für generischen Typ Argument ist für verschachtelte Typen nicht sichtbar? nicht das Verhalten der folgenden Code erhalten

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

} 

EDIT: das tatsächliche Ergebnis ist:

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=sun.reflect.annotation.AnnotatedT[email protected] 
annotations=[] 
type=class java.lang.Integer 

Warum die Anordnung von erklärt Anmerkungen auf Typargument ist leer, wenn der umgebende Typ verschachtelt ist? Ich erwarte, dass ich ein Element wie für den Top-Level-Typ habe. Ich würde mich über jede Erklärung auf der Grundlage von JLS freuen.

Happens konsequent auf JDK8u101 (http://compilejava.net), ältere JDK8 und Eclipse.

Danke!

Antwort

5

gab ich einige Zeit, um das zu Debuggen und die annotatedParameterizedType Variable scheint immer noch die Referenz auf die Anno-Annotation in seinem allOnSameTargetTypeAnnotations Feld für den verschachtelten Fall zu

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 

Allerdings gibt enthalten ist ein Unterschied in der Positionstiefe und die kommende getAnnotatedActualTypeArguments() -Methode von AnnotatedTypeFactory enthält einen TypeAnnotation.isSameLocationInfo() - Vergleich als eine Vorbedingung zum Hinzufügen von Elementen zu den Annotationen Karte, die im verschachtelten Fall falsch wird, also wird schließlich kein Element hinzugefügt

Ich habe auch keine Dokumentation gefunden. Vielleicht haben Sie hier ein Problem gefunden

+2

Ich denke, wir können es zurückverfolgen auf [ 'AnnotatedTypeFactory' , Zeile 105] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/sun/reflect/annotation/AnnotatedTypeFactory.java#105) wo verschachtelte parametrisierte Typen sind unbedingt behandelt als (nicht-static) innere Klassen (im Gegensatz zu verifizierbaren Typen, sieben Zeilen früher). In der Tat, ein 'ParameterterrizedType' zu ​​fragen, ob es" statisch "ist, ist nicht einfach ... – Holger

4

Dies ist ein Fehler in der OpenJDK, ich habe dies vor einer Weile gemeldet und ich hoffe, dass es behoben wird. Typ Anmerkungen werden in der Praxis nicht so oft verwendet und es scheint keine Priorität zu sein. Wie Holger bereits erwähnt hat, ist dies eine Verwechslung in der Implementierung der AnnotatedTypeFactory.

Sie können Byte Buddy verwenden, die korrekt die Klassendatei Metadaten analysiert:

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()); 
} 

Dies gibt Ihnen die erwartete Ausgabe:

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, du meinst, der Fehler war vorher nicht bekannt? Und könnten Sie bitte URL des gemeldeten Fehlers angeben? Oracle Bug Datenbank-Suchmaschine scheint im Moment etwas ungesund. –

+1

Ich habe versucht, es zu finden, aber ich konnte es nicht. Ich habe es über das Webformular gemeldet, so dass mein Name nicht auf dem Problem steht. Ich habe über 20 Bugs berichtet, die sich auf Typ-Annotationen beziehen, daher ist es nicht-trivial, sorry. Sie sind leider ziemlich buggy. Dieser Bericht sollte jetzt ungefähr ein Jahr alt sein. –

+1

Hi Rafael, können Sie bitte versuchen, den Fehlerbericht erneut zu finden? Ich versuche herauszufinden, ob ich einen Bericht für [ein ähnliches Problem] einreichen sollte (http://stackoverflow.com/questions/42512701/type-use-annotats-get-lost-when-type-is-nested-generic -Schnittstelle). – Tillerino

Verwandte Themen