2013-05-26 6 views
6

Ist die Java-Annotationsreihenfolge zur Laufzeit persistent? Ich habe OpenJDK 1.7.0_21 überprüft - es behält die Reihenfolge der Anmerkungen bei. Kann ich diese Persistenz auf allen Java-VMs erwarten?Ist die Java-Annotationsreihenfolge persistent?

+2

Ich bin neugierig: Wie würde das sein? – acdcjunior

+0

Ich möchte wissen, ob ich zusätzliche Anmerkungen verwenden kann, um zusätzliche Argumente für frühere Anmerkungen anzugeben (zB @DoSomething ("f1") @Arg ("arg1") @Arg ("arg2") @DoSomething ("f2") @ Arg ("arg2.1") @Arg ("arg2.2")) – Azazar

+0

Ich würde das nicht tun ... scheint verwirrend. Was ist das Problem mit plain '@DoSomething (Wert =" f1 ", a1 =" arg1 ", a2 =" arg2 "); @DoSomething (Wert = "f2", a1 = "arg2.1", a2 = "arg2.2"); '? – acdcjunior

Antwort

4

Hängt davon ab, was Sie mit "hartnäckig" meinen. Ich denke, Sie könnten etwas in der Frage impliziert haben, also hier ist ein paar Q & A:

Ist die Annotation Reihenfolge persistent?
Ja, es ist in der .class Datei in einer Reihenfolge geschrieben, die sich nicht ändert.

Stimmt die Reihenfolge der Annotationen in der .class-Datei mit der Reihenfolge der Annotationen im Quellcode überein?
Ja. Wenn Sie Ihren Code kompilieren ...

@Column(length = 256) 
@NotBlankConstraint(message = "The application title must be set.") 
@Size(min = 1, max = 256, message = "The application title must be set and not longer than 250 characters.") 
private String title; 

und überprüfen Sie mit javap -v:

#67 = Utf8    Ljavax/validation/constraints/Size; 
... 
private java.lang.String title; 
    descriptor: Ljava/lang/String; 
    flags: ACC_PRIVATE 
    RuntimeVisibleAnnotations: 
    0: #50(#62=I#63) 
    1: #64(#65=s#66) 
    2: #67(#68=I#69,#70=I#63,#65=s#71 

Wenn Sie die Reihenfolge der Anmerkungen ändern, wird die Reihenfolge, in der Byte-Code als auch ändern. Getestet mit OpenJDK 1.8.0_121, aber ich denke, das ist auch bei früheren JDKs der Fall.

Wird die Reihenfolge vom Bytecode durch die getAnnotations() Methode beibehalten?
Ja, von dem, was ich sehen kann, gibt es konsequent die gleiche Reihenfolge wie im Byte-Code in der Datei .class.

Wird getAnnotations() garantiert die Bytecode Annotations Reihenfolge in der Zukunft widerspiegeln?
Nein. Wie von der anderen Antwort geantwortet, ist dieses Verhalten nicht dokumentiert, so dass in einer öffentlich zugänglichen Bibliothek nicht darauf vertraut werden kann.
Allerdings gibt es subtle signs that the order should be kept irgendwie.

Nun zu Ihrem Zweck, Wenn es garantiert war, sollte ich die Reihenfolge verwenden, um einige Anmerkungen für einige vorherige Anmerkungen gelten?
Das ist eine Frage des Geschmacks, aber ich würde sagen, dass die meisten Java-Programmierer das nicht mögen würden. Es wäre nicht viel intuitiver und lesbarer Code. Ich würde vorschlagen Gruppe der Anmerkungen so wie

@ValidationGroup(
    validators = { @NotNull, @NotEmpty }, 
    message = "User name must be filled." 
) 
public String getUsername(); 

Das Problem dabei ist, dass Sie nicht ein Array von „jeder Anmerkung“ haben können, und da es für Anmerkungen keine Vererbung ist, ist dies nicht getan werden kann (Java 1.8). Daher greifen verschiedene Frameworks auf das zurück, was Bean Validation verwendet - siehe das Konzept von Gruppen.

Zum Schluss möchte ich noch auf Eric's Kommentar verweisen, um JSR 303 zu überprüfen, es ist ziemlich gut gemacht und auch in viele andere Bibliotheken wie RestEasy integriert.

+0

Ein Teil Ihres Beispiels sieht nicht möglich aus: 'validators = {@NotNull, @NotEmpty}' Ist das ein Versehen, oder können Sie eine Definition des Mitglieds 'validators() 'angeben, die diese Art der Verwendung erlaubt? –

+0

@GlennLane, du hast Recht. Ich werde es mit einem besseren Beispiel beheben. –

1

java.lang.reflect.AnnotatedElement.getAnnotations() API sagt, dass es alle Anmerkungen zurückgibt, die auf diesem Element vorhanden sind. Er sagt nichts über die Reihenfolge aus, in der diese Annotationen zurückgegeben werden.

+1

Überprüfen Sie diese Antwort: http://StackOverflow.com/A/30222541/810109 - in Bezug auf die Anmerkungen werden in einer ** garantierten ** Reihenfolge abgerufen. – mkurz

-4

In Java 7 und niedriger können Sie nicht mehrere Annotationen desselben Typs auf einem Element haben. Sie können sie Teil des Wertes einer anderen Anmerkung machen:

// JSR 303 
@Pattern.List({ 
    @Pattern(regexp="\\w{8,14}"), 
    @Pattern(regexp=".*Z.*") 
}) 
public String getCode() { 
    return code; 
} 

Java 8 wird dies zu entspannen. Siehe Oracle's bug tracker. Dies wurde unter Stack Overflow diskutiert.

+1

Dies beantwortete nicht die Frage, ob eine Bestellung wichtig ist oder nicht. Wenn du 'public void method (@Foo @Bar String str)' hast, wäre es nett anzunehmen, dass wenn ich es zum Verarbeitungsbalken mache, dass es alle Kriterien von foo erfüllt. – corsiKa