为什么不能在Java中扩展注释?

我不明白为什么在Java注释中没有inheritance,就像Java类一样。 我认为这将是非常有用的。

例如:我想知道给定的注释是否是一个validation器。 通过inheritance,我可以自反地浏览超类来知道这个注释是否扩展了ValidatorAnnotation 。 否则,我怎么能做到这一点?

那么,任何人都可以给我一个这个devise决定的理由吗?

关于为什么它不是这样devise的,你可以在JSR 175deviseFAQ中find答案,其中说:

为什么不支持注释子types(其中一个注释types扩展了另一个)?

这使注解types系统变得复杂,并且使“特定工具”的编写变得更加困难。

“特定工具” – 查询任意外部程序的已知注释types的程序。 例如,存根发生器就属于这一类。 这些程序将读取带注释的类,而不会将其加载到虚拟机中,但会加载注释接口。

所以,我想是的,原因就是KISS。 无论如何,似乎这个问题(以及其他许多问题)正在作为JSR 308的一部分进行研究,您甚至可以find由Mathias Ricken开发的具有此function的替代编译器。

可扩展注释将有效地增加指定和维护另一个types系统的负担。 这将是一个相当独特的types系统,所以你不能简单地应用OOtypes范例。

在将多态性和inheritance引入到注释中时,请考虑所有问题(例如,当子注释更改元注释规范(如保留)时会发生什么情况?

所有这些增加了什么用例的复杂性?

你想知道给定的注释是否属于一个类别?

尝试这个:

 @Target(ElementType.ANNOTATION_TYPE) public @interface Category { String category(); } @Category(category="validator") public @interface MyFooBarValidator { } 

正如您所看到的,您可以使用提供的工具轻松对批注进行分组和分类。

所以, KISS是没有向Java语言引入元types系统的原因。

[ps编辑]

我只是为了演示而使用了string,并且考虑了开放式元注释。 对于你自己给定的项目,你显然可以使用类别types的枚举,并给定一个给定的注解指定多个类别(“多重inheritance”)。 请注意,这些值完全是虚假的,仅用于演示目的:

 @Target(ElementType.ANNOTATION_TYPE) public @interface Category { AnnotationCategory[] category(); } public enum AnnotationCategory { GENERAL, SEMANTICS, VALIDATION, ETC } @Category(category={AnnotationCategory.GENERAL, AnnotationCategory.SEMANTICS}) public @interface FooBarAnnotation { } 

从某种意义上说,你已经使用注释 – 元注释。 如果您使用元信息注释注释,则在许多方面等同于扩展其他接口。 注解是接口,所以多态并不真正起作用,而且由于它们本质上是静态的,所以不会有运行时dynamic调度。

在你的validation器的例子中,你可以在注释中获得注释types,看看它是否有一个validation器元注释。

唯一的例子是我可以看到inheritance会有所帮助,如果你想能够通过超types来获得注解,但这会增加一大堆的复杂性,因为给定的方法或types可能有两个这样的注释,这意味着一个数组将不得不返回而不是一个单一的对象。

所以我认为最终的答案是,用例是深奥的,使更多的标准用例复杂化,使其不值得。

从来没有想过,但是…似乎你是对的,注释inheritance设施没有问题(至less我没有看到它的问题)。

关于你的例子'validation'注释 – 你可以利用'元注释'的方法。 即,您将特定的元注释应用于整个注释界面。

Java注释支持的devise人员对Java社区造成了一些“简化”。

  1. 没有注释子types,使许多复杂的注释不必要的丑陋。 一个人不能简单地在一个注解中拥有一个可以拥有三件事情之一的属性。 一个需要有三个独立的属性,混淆开发人员,并要求运行时validation,以确保只有三个使用中的一个。

  2. 每个站点只有一个给定types的注释。 这导致了完全不必要的集合注释模式。 @Validation和@Validations,@Image和@Images等

第二个正在Java 8中被修复,但是为时已晚。 许多框架都是基于Java 5中的可能性编写的,而现在这些API疣是在这里停留很长时间的。

我有同样的问题。 不,你不能。 我自己“自律”地在注解中写属性来尊重某些标准,所以在外部当你注释时,你可以通过它的属性“嗅探”它是什么types的注释。

有一件事我能想到的是有多个注释的可能性。 所以你可以在同一个地方添加validation器和更具体的注释。 但我可能会误会:)

我可能会迟到三年来回答这个问题,但是我发现它很有趣,因为我发现自己在同一个地方。 这是我的承诺。 您可以将注释视为Enums。 他们提供了一种单向的信息 – 使用它或丢失它。

我有一种情况,我想在一个Web应用程序中模拟GET,POST,PUT和DELETE。 我非常想要有一个名为“HTTP_METHOD”的“超级”注释。 后来我才明白,这并不重要。 那么,我必须解决在HTML表单中使用隐藏的字段来确定DELETE和PUT(因为无论如何POST和GET都可用)。

在服务器端,我查找了名为“_method”的隐藏请求参数。 如果该值是PUT或DELETE,则会覆盖相关的HTTP请求方法。 话虽如此,我是否需要延伸诠释才能完成工作并不重要。 所有的注释看起来都是一样的,但是在服务器端他们被区别对待。

所以在你的情况下,放弃痒扩展注释。 把它们当作“标记”。 他们“代表”一些信息,而不一定“操纵”一些信息。