Is Java annotation order persistent?

2019-04-25 11:47发布

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?

3条回答
成全新的幸福
2楼-- · 2019-04-25 12:25

In Java 7 and lower, you cannot have multiple annotations of the same type on an element. You can make them part of the value of another annotation:

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

Java 8 will be relaxing this. See Oracle's bug tracker. This was discussed at Stack Overflow.

查看更多
姐就是有狂的资本
3楼-- · 2019-04-25 12:33

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.

查看更多
Ridiculous、
4楼-- · 2019-04-25 12:42

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

查看更多
登录 后发表回答