2013-05-26 8 views
6

L'ordine delle annotazioni Java è persistente in fase di runtime? Ho controllato OpenJDK 1.7.0_21 - mantiene l'ordine delle annotazioni. Posso aspettarmi che la persistenza su tutte le VM java?L'ordine delle annotazioni Java è persistente?

+2

Sono curioso: come sarebbe? – acdcjunior

+0

Voglio sapere se posso usare annotazioni aggiuntive per specificare argomenti aggiuntivi per annotazioni precedenti (ad es. @DoSomething ("f1") @Arg ("arg1") @Arg ("arg2") @DoSomething ("f2") @ Arg ("arg2.1") @Arg ("arg2.2")) – Azazar

+0

Non lo farei ... sembra confusionario. Qual è il problema con plain '@DoSomething (value =" f1 ", a1 =" arg1 ", a2 =" arg2 "); @DoSomething (value = "f2", a1 = "arg2.1", a2 = "arg2.2"); '? – acdcjunior

risposta

4

Dipende da cosa intendi per "persistente". Penso che potresti aver inteso qualcosa implicito nella domanda, quindi ecco alcuni Q & A:

L'ordine di annotazione è persistente?
Sì, è scritto nel file .class in un ordine che non cambia.

L'ordine delle annotazioni nel file .class riflette l'ordine delle annotazioni nel codice sorgente?
Sì. Se si compila il codice di ...

@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; 

e verificare con 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 

Se si modifica l'ordine delle annotazioni, l'ordine nel bytecode cambierà pure. Testato con OpenJDK 1.8.0_121, ma penso che sia il caso anche per i JDK precedenti.

L'ordine dal bytecode è mantenuto con il metodo getAnnotations()?
Sì, da quello che riesco a vedere, viene costantemente restituito lo stesso ordine presente nel codice byte nel file .class.

È garantito che lo getAnnotations() rispecchi l'ordine delle annotazioni di bytecode in futuro?
No. Come risposto dall'altra risposta, questo comportamento non è documentato, quindi non può essere fatto valere in una libreria disponibile pubblicamente.
Tuttavia, ci sono subtle signs that the order should be kept in qualche modo.

Ora al tuo scopo, Se è stato garantito, dovrei usare l'ordine per fare applicare alcune annotazioni ad alcune annotazioni precedenti?
Questa è una questione di gusti, ma direi che alla maggior parte dei programmatori Java non piacerebbe. Non sarebbe un codice molto intuitivo e leggibile. Vorrei suggerire di raggruppare le annotazioni, come

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

Il problema di questo è che non si può avere una serie di "qualsiasi annotazione", e dal momento che non c'è alcuna eredità per le annotazioni, questo non può essere fatto (Java 1.8). Quindi vari framework ricorrono a ciò che usa Bean Validation - vedete il concetto di gruppi.

Infine, ho in secondo luogo il commento di Eric per controllare JSR 303, è abbastanza ben fatto e anche integrato in molte altre librerie come RestEasy.

+0

Parte del tuo esempio non sembra possibile: 'validators = {@NotNull, @NotEmpty}' È una svista, o puoi fornire una definizione del membro 'validators()' che permette questo tipo di utilizzo? –

+0

@GlennLane, hai ragione. Risolverò con un esempio migliore. –

1

java.lang.reflect.AnnotatedElement.getAnnotations() API dice che restituisce tutte le annotazioni presenti su questo elemento. Non dice nulla sull'ordine in cui queste annotazioni vengono restituite

+1

Leggi questa risposta: http://stackoverflow.com/a/30222541/810109 - riguardo ad esso le annotazioni vengono recuperati in un ordine ** garantito **. – mkurz

-4

In Java 7 e versioni precedenti, non è possibile avere più annotazioni dello stesso tipo su un elemento. Puoi renderli parte del valore di un'altra annotazione:

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

Java 8 si rilassa. Vedi Oracle's bug tracker. Questo è stato discusso al Stack Overflow.

+1

Questo non ha risposto alla domanda se l'ordine conta o no. Se hai 'metodo public void (@Foo @Bar String str)', sarebbe bello presumere che se lo faccio alla barra di elaborazione soddisfi tutti i criteri di foo. – corsiKa

Problemi correlati