Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Java annotation order persistent?

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?

like image 776
Mikhail Yevchenko Avatar asked May 26 '13 04:05

Mikhail Yevchenko


2 Answers

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.

like image 145
Ondra Žižka Avatar answered Nov 14 '22 15:11

Ondra Žižka


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

like image 26
Evgeniy Dorofeev Avatar answered Nov 14 '22 15:11

Evgeniy Dorofeev