2017-09-07 1 views
0

Ich habe eine SubClass und eine SuperClass, sowie eine Anmerkung DocAnnotation. Ich brauche einen Anruf an SubClass.foo(), um alle Klassenanmerkungen von SubClass und SuperClass zu erhalten. Die Klassen sind wie folgt definiert:@herited Annotation wird nicht vererbt

Oberklasse

package Code 

import Annotations.DocAnnotation; 
import java.util.Arrays; 

@DocAnnotation("Super Annotation") 
public class SuperClass { 

    public void foo() { 
     System.out.println(Arrays.toString(this.getClass().getAnnotations())); 
     System.out.println(Arrays.toString(this.getClass().getDeclaredAnnotations())); 
    } 
} 

SubClass

package Code; 

import Annotations.DocAnnotation; 

@DocAnnotation("Sub Annotation") 
public class SubClass extends SuperClass{ 
} 

DocAnnotation

package Annotations; 

import java.lang.annotation.Inherited; 
import java.lang.annotation.Repeatable; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 

@Inherited 
@Retention(RetentionPolicy.RUNTIME) 
@Repeatable(DocAnnotations.class) 
public @interface DocAnnotation { 
    String value(); 
} 

Lauf SubClass.foo Ich erwarte, dass "Super Annotation" und "Sub Annotation" beide sehen, sondern ich siehe nur [@Annotations.DocAnnotation(value=Sub Annotation)]. Missverstehe ich, was @inherited tut, oder mache ich etwas falsch?


Edit:

Nach dem Hinzufügen der Annotation @DocAnnotation("Super Annotation")-SubClass (das ist das gleiche wie in SuperClass) zweimal tatsächlich auftaucht, einmal für den Einsatz in SubClass und einmal für den Einsatz in SuperClass! Jetzt bin ich fast sicher, dass ich etwas falsch verstehe ...

Antwort

2

Dies scheint das gewünschte Verhalten zu sein, oder zumindest ist es festgelegt, so arbeiten (doc):

Wenn [...] die Benutzer der Annotationstyp auf einer Klassendeklaration abfragt, und Die Klassendeklaration enthält keine Annotation für diesen Typ, dann wird die Superklasse der Klasse automatisch nach dem Annotationstyp abgefragt.

Mit anderen Worten, da SubClass bereits mit @DocAnnotation kommentiert wird, wird die übergeordnete Klasse nicht abgefragt.

Bei näherer Betrachtung scheint das Verhalten ein wenig komisch, vor allem nach dem Experimentieren mit dem Vorhandensein des enthaltenden Annotationstyps.Ich kam mit dem folgenden Beispiel oben, die diese (link) veranschaulicht:

import java.lang.annotation.*; 
import java.util.*; 

@Inherited 
@Repeatable(Container.class) 
@Retention(RetentionPolicy.RUNTIME) 
@interface Ann { 
    String value(); 
} 

@Inherited 
@Retention(RetentionPolicy.RUNTIME) 
@interface Container { 
    Ann[] value(); 
} 

// Basic case. Result is that 
// only @Ann("2") is present on 
// ExhibitASub. 
@Ann("1") 
class ExhibitASuper { 
} 
@Ann("2") 
class ExhibitASub extends ExhibitASuper { 
} 

// Because this case results in the 
// @Container being present on ExhibitBSuper, 
// rather than @Ann, all three annotations 
// end up appearing on ExhibitBSub. 
@Ann("1") 
@Ann("2") 
class ExhibitBSuper { 
} 
@Ann("3") 
class ExhibitBSub extends ExhibitBSuper { 
} 

// Similar to the preceding case, by 
// forcing the use of @Container, both 
// annotations are present on ExhibitCSub. 
@Container(@Ann("1")) 
class ExhibitCSuper { 
} 
@Ann("2") 
class ExhibitCSub extends ExhibitCSuper { 
} 

// Yet when we force both to use @Container, 
// only @Container(@Ann("2")) is present on 
// ExhibitDSub. 
@Container(@Ann("1")) 
class ExhibitDSuper { 
} 
@Container(@Ann("2")) 
class ExhibitDSub extends ExhibitDSuper { 
} 

class Main { 
    public static void main(String[] args) { 
     for (Class<?> cls : Arrays.asList(ExhibitASub.class, 
              ExhibitBSub.class, 
              ExhibitCSub.class, 
              ExhibitDSub.class)) { 
      System.out.printf("%s:%n", cls); 
      for (Annotation ann : cls.getAnnotations()) { 
       System.out.printf(" %s%n", ann); 
      } 

      System.out.println(); 
     } 
    } 
} 

der Ausgang davon ist wie folgt:

class ExhibitASub: 
    @Ann(value=2) 

class ExhibitBSub: 
    @Container(value=[@Ann(value=1), @Ann(value=2)]) 
    @Ann(value=3) 

class ExhibitCSub: 
    @Container(value=[@Ann(value=1)]) 
    @Ann(value=2) 

class ExhibitDSub: 
    @Container(value=[@Ann(value=2)]) 

beachte, daß für B und C wir sowohl die Anmerkungen auf der übergeordneten Klasse sehen und Unterklasse. Vermutlich liegt dies daran, dass (im engeren Sinne) die in der Oberklasse vorhandene Anmerkung von einem anderen Typ ist als die Anmerkung, die in der Unterklasse vorhanden ist. Beachten Sie, dass wir für D nur die Annotation der Unterklasse sehen, da beide Klassen den Containertyp verwenden.

die enthält Annotationstyp Verwendung ausdrücklich eine Abhilfe für einige Fälle sein könnte, aber es ist nicht eine allgemeine Lösung wegen Fall D.

Ich könnte einen Fehlerbericht für diese morgen Datei, da diese ziemlich unerwünscht scheint. Da @Inherited älter als @Repeatable ist, konnte dieses Verhalten von früheren Versionen stammen, in denen diese Situation nicht auftreten konnte.

+0

Ich habe die Containeranmerkung total vergessen! Das hat mich wirklich zu einer Schleife gebracht ... Weißt du, ob das Verhalten, das ich beschreibe, möglich ist? Ich könnte direkt alle Klassen abfragen, die die Unterklasse erweitert, aber das scheint hässlicher Code zu sein. Gibt es eine bessere Lösung? – bendl

+0

Ich glaube nicht. Eine andere Lösung könnte darin bestehen, Annotationen ganz aufzugeben und eine Schnittstelle zu verwenden. Ich kann nicht wirklich sagen, ob das für Ihren Fall besser ist, aber es könnte funktionieren, da Sie den Kurs kommentieren. – Radiodef

+0

Ich denke, ich werde mich an Anmerkungen halten müssen, aber danke! Wenn du am Ende einen Fehlerbericht einreichst, poste bitte einen Link hier. Ich wäre interessiert zu wissen, ob Oracle auch dieses Verhalten erwartet. – bendl

2

Sie erhalten diese Anmerkung falsch. Die javadoc gibt eindeutig an:

Zeigt an, dass ein Anmerkungstyp automatisch geerbt wird. Wenn eine vererbte Metaanmerkung in einer Annotationstypdeklaration vorhanden ist und der Benutzer den Annotationstyp für eine Klassendeklaration abfragt und die Klassendeklaration keine Annotation für diesen Typ aufweist, wird die Superklasse der Klasse automatisch nach dem Annotationstyp abgefragt.

Mit anderen Worten: Wenn Sie die Unterklasse abfragen, dann würden Sie die Superklasse werden kommentiert finden. Aber dieses Ding ist nicht gemeint für Vererbung im "OO-Sinn". Wenn Sie beide Annotationen sehen möchten, müssen Sie Code schreiben, der jede Klasse im Klassenvererbungsbaum manuell überprüft.

Verwandte Themen