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

为什么不能在Java中扩展注释?,java,inheritance,annotations,Java,Inheritance,Annotations,我不明白为什么Java注释中没有继承,就像Java类一样。我认为这会非常有用 例如:我想知道给定的注释是否是验证器。通过继承,我可以反射性地浏览超类,以了解此注释是否扩展了ValidatorAnnotation。否则,我如何才能做到这一点 那么,有人能给我一个做出这个设计决定的理由吗?我也有同样的问题。不,你不能。我确实“训练”自己在注释中编写属性以遵守一些标准,所以在外部,当您得到注释时,您可以通过其属性“嗅探”它是什么类型的od注释 我能想到的一件事是有多个注释的可能性。因此,您可以在同一位

我不明白为什么Java注释中没有继承,就像Java类一样。我认为这会非常有用

例如:我想知道给定的注释是否是验证器。通过继承,我可以反射性地浏览超类,以了解此注释是否扩展了
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社区进行了大量的“简化”

  • 无注释子类型会使许多复杂注释变得不必要的丑陋。不能简单地在注释中包含一个属性,该属性可以包含以下三种内容之一。一个需要有三个单独的属性,这会混淆开发人员,需要运行时验证以确保只使用三个属性中的一个

  • 每个站点只有一个给定类型的注释。这导致了完全不必要的集合注释模式@验证和@Va