为什么不能在Java中扩展注释?
我不明白为什么Java注释中没有继承,就像Java类一样。我认为这会非常有用 例如:我想知道给定的注释是否是验证器。通过继承,我可以反射性地浏览超类,以了解此注释是否扩展了为什么不能在Java中扩展注释?,java,inheritance,annotations,Java,Inheritance,Annotations,我不明白为什么Java注释中没有继承,就像Java类一样。我认为这会非常有用 例如:我想知道给定的注释是否是验证器。通过继承,我可以反射性地浏览超类,以了解此注释是否扩展了ValidatorAnnotation。否则,我如何才能做到这一点 那么,有人能给我一个做出这个设计决定的理由吗?我也有同样的问题。不,你不能。我确实“训练”自己在注释中编写属性以遵守一些标准,所以在外部,当您得到注释时,您可以通过其属性“嗅探”它是什么类型的od注释 我能想到的一件事是有多个注释的可能性。因此,您可以在同一位
ValidatorAnnotation
。否则,我如何才能做到这一点
那么,有人能给我一个做出这个设计决定的理由吗?我也有同样的问题。不,你不能。我确实“训练”自己在注释中编写属性以遵守一些标准,所以在外部,当您得到注释时,您可以通过其属性“嗅探”它是什么类型的od注释 我能想到的一件事是有多个注释的可能性。因此,您可以在同一位置添加验证器和更具体的注释。但是我可能弄错了:)从来没有想过,但是。。。看来您是对的,注释继承功能没有问题(至少我看不出它有什么问题)
关于您的“验证器”注释示例-您可以利用“元注释”方法。例如,将特定的元注释应用于整个注释接口。可扩展注释将有效地增加指定和维护另一类型系统的负担。这将是一个相当独特的类型系统,因此您不能简单地应用OO类型范例 当您将多态性和继承引入注释时,请仔细考虑所有问题(例如,当子注释更改元注释规范(如保留)时会发生什么情况?) 所有这些都增加了什么用例的复杂性 您想知道给定注释是否属于某个类别 试试这个:
@Target(ElementType.ANNOTATION_TYPE)
public @interface Category {
String category();
}
@Category(category="validator")
public @interface MyFooBarValidator {
}
正如您所看到的,您可以使用提供的工具轻松地对注释进行分组和分类,而不会带来不必要的麻烦
因此,这就是为什么不在Java语言中引入元类型系统的原因
[附后编辑]
我使用这个字符串只是为了演示和查看一个开放式元注释。对于您自己的给定项目,显然可以使用类别类型的枚举,并为给定注释指定多个类别(“多重继承”)。请注意,这些值完全是假的,仅用于演示目的:
@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 {
}
从某种意义上说,你已经有了注释-元注释。如果使用元信息对注释进行注释,这在许多方面相当于扩展一个附加接口。注释是接口,所以多态性并没有真正发挥作用,因为它们本质上是静态的,所以不可能有运行时动态调度 在您的验证器示例中,您可以在注释上获取注释类型,并查看它是否具有验证器元注释 我所能看到的唯一一个继承有帮助的用例是,如果您希望能够通过超级类型获得注释,但这会增加一大堆复杂性,因为给定的方法或类型可能有两个这样的注释,这意味着必须返回一个数组,而不仅仅是一个对象
因此,我认为最终的答案是,用例是深奥的,并且使更多的标准用例变得复杂,因此不值得使用。关于它为什么没有这样设计的原因,您可以在设计常见问题中找到答案,其中说: 为什么不支持注释子类型(一种注释类型扩展另一种注释类型) 它使注释类型复杂化 系统,并使其更加 难以编写“特定工具” “特定工具”-用于查询 任意类型的已知注释 外部程序。短线发生器, 例如,属于这一类。 这些程序将读取注释 类,而不将它们加载到 虚拟机,但将加载 注释接口
所以,是的,我想,原因是它只是亲吻。无论如何,这个问题(以及其他许多问题)似乎正在作为的一部分进行研究,您甚至可以找到一个具有此功能的替代编译器。我可能晚了三年才回答这个问题,但我发现它很有趣,因为我发现自己也在这个问题上。这是我的看法。可以将批注作为枚举查看。它们提供的信息是单向的——要么使用,要么丢失 我曾经遇到过这样一种情况,我想在web应用程序中模拟GET、POST、PUT和DELETE。我非常希望有一个名为“HTTP_方法”的“超级”注释。后来我才明白这没关系。嗯,我不得不在HTML表单中使用一个隐藏字段来标识DELETE和PUT(因为POST和GET无论如何都是可用的) 在服务器端,我查找了一个名为“\u method”的隐藏请求参数。如果该值是PUT或DELETE,那么它将覆盖相关的HTTP请求方法。话虽如此,我是否需要扩展注释来完成工作并不重要。所有注释看起来都一样,但在服务器端的处理方式不同
因此,在您的情况下,不要急于扩展注释。将它们视为“标记”。它们“代表”某些信息,而不一定“操纵”某些信息。Java注释支持的设计者对Java社区进行了大量的“简化”