【问题标题】:Is Java annotation order persistent?Java注释顺序是否持久?
【发布时间】:2013-05-26 04:43:10
【问题描述】:

Java 注释顺序是否在运行时保持不变?我检查了 OpenJDK 1.7.0_21 - 它保留了注释顺序。我可以期待所有 Java VM 上的持久性吗?

【问题讨论】:

  • 我很好奇:这有什么关系?
  • 我想知道,如果我可以使用额外的注释来为早期的注释指定额外的参数(例如@DoSomething("f1") @Arg("arg1") @Arg("arg2") @ DoSomething("f2") @Arg("arg2.1") @Arg("arg2.2") )
  • 我不会那样做...看起来很混乱。普通的@DoSomething(value="f1", a1="arg1", a2="arg2"); @DoSomething(value="f2", a1="arg2.1", a2="arg2.2"); 有什么问题?
  • 我猜这不是正确的例子,它真的很混乱。我正在研究 HTML 表单验证器,它从方法和字段注释中加载所有验证请求。因此验证器注释可能如下所示: @Field("username") @NotEmpty @ErrorMessage("Requred Field") @Validator(controller.users.NewUsernameValidator.class) @ErrorMessage("This username is already used") public String getUsername () ...但这只有在注释顺序是持久的情况下才有效,否则,我必须将 errorMessage 字符串作为参数放入每个注释。
  • 您是否尝试从头开始重做 JSR 303 及其实现?查看 Hibernate Validator。

标签: java reflection annotations


【解决方案1】:

取决于您所说的“持久”是什么意思。我认为您的意思可能暗示了问题中的某些内容,因此这里有一些问答:

注释顺序是否持久?
是的,它以不变的顺序写入.class 文件中。

.class 文件中的注释顺序是否反映了源代码中的注释顺序?
是的。如果你编译你的代码...

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

并与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

如果你改变注解的顺序,字节码的顺序也会改变。使用 OpenJDK 1.8.0_121 进行测试,但我认为早期的 JDK 也是如此。

getAnnotations() 方法是否保留了来自字节码的顺序?
是的,据我所见,它始终返回与.class 文件中的字节码相同的顺序。

getAnnotations() 是否保证将来反映字节码注释顺序?
否。正如另一个答案所回答的那样,这种行为没有记录在案,因此不能在公开可用的库中依赖。
但是,不知何故有subtle signs that the order should be kept

现在到你的目的, 如果有保证,我是否应该使用订单将某些注释应用于以前的某些注释?
这是个人喜好问题,但我想说大多数 Java 程序员不喜欢这样。它不会是太多直观和可读的代码。我建议将注释分组,例如

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

这样做的问题是你不能有一个“任何注释”的数组,并且由于注释没有继承,所以不能这样做(Java 1.8)。因此,各种框架都求助于 Bean Validation 使用的东西 - 请参阅它的组概念。

最后,我想支持 Eric 的评论来检查 JSR 303,它做得很好,并且还集成到了 RestEasy 等许多其他库中。

【讨论】:

  • 您的部分示例看起来不可能:validators = { @NotNull, @NotEmpty } 这是一个疏忽,还是您可以提供允许这种用法的validators() 成员的定义?
  • @GlennLane,你是对的。我会用更好的例子来解决。
【解决方案2】:

java.lang.reflect.AnnotatedElement.getAnnotations() API 表示它返回此元素上存在的所有注释。它没有说明返回这些注释的顺序

【讨论】:

【解决方案3】:

在 Java 7 及更低版本中,您不能在一个元素上拥有多个相同类型的注解。您可以使它们成为另一个注释的值的一部分:

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

Java 8 将放宽这一点。见Oracle's bug tracker。这在Stack Overflow 进行了讨论。

【讨论】:

  • 这并没有回答订单是否重要的​​问题。如果你有public void method(@Foo @Bar String str),最好假设如果我进入处理栏,它符合 foo 的所有标准。
猜你喜欢
  • 1970-01-01
  • 2016-05-02
  • 1970-01-01
  • 2012-11-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-04
  • 1970-01-01
  • 2011-11-23
相关资源
最近更新 更多