Is Java annotation order persistent at runtime? I've checked OpenJDK 1.7.0_21 - it preserves annotations order. Can I expect that persistence on all java VMs?
Depends on what you mean by "persistent". I think you might have meant something implied in the question, so here's few Q&A:
Is the annotation order persistent?
Yes, it's written in the .class
file in an order that doesn't change.
Does the annotations order in the .class
file reflect the annotations order in the source code?
Yes. If you compile your code...
@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;
and check with 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
If you change the order of the annotations, the order in the byte code will change as well. Tested with OpenJDK 1.8.0_121, but I think that's the case for earlier JDKs too.
Is the order from the bytecode kept by the getAnnotations()
method?
Yes, from what I can see, it is consistently returning the same order as is in the byte code in the .class
file.
Is getAnnotations()
guaranteed to reflect the bytecode annotations order in the future?
No. As replied by the other answer, this behavior is not documented, so can't be relied on in a publicly available library.
However, there are subtle signs that the order should be kept somehow.
Now to your purpose,
If it was guaranteed, should I use the order to have some annotation apply to some previous annotations?
That's a matter of taste, but I would say that most Java programmers wouldn't like that. It wouldn't be much intuitive and readable code. I would suggest to group the annotations such like
@ValidationGroup(
validators = { @NotNull, @NotEmpty },
message = "User name must be filled."
)
public String getUsername();
The problem with this is that you can't have an array of "any annotation", and since there's no inheritance for annotations, this can't be done (Java 1.8). So various frameworks resort to what Bean Validation uses - see it's concept of groups.
Lastly, I'd second to Eric's comment to check JSR 303, it's quite well done and also integrated into many other libraries like RestEasy.
java.lang.reflect.AnnotatedElement.getAnnotations()
API says that it returns all annotations present on this element. It says nothing about the order in which these annotations are returned
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With