为什么在Java中无法扩展注释?

2022-08-31 05:40:05

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

例如:我想知道给定的注释是否是验证器。通过继承,我可以条件反射地浏览超类,以了解此注释是否扩展了 .否则,我该如何做到这一点?ValidatorAnnotation

那么,谁能给我一个设计决定的理由呢?


答案 1

关于它不是以这种方式设计的原因,你可以在JSR 175设计FAQ中找到答案,它说:

为什么不支持批注子类型(其中一种批注类型扩展另一种批注类型)?

它使注释类型系统复杂化,并使编写“特定工具”变得更加困难。

...

“特定工具” — 查询任意外部程序的已知注释类型的程序。例如,存根生成器就属于这一类。这些程序将读取带注释的类,而无需将它们加载到虚拟机中,但将加载注释接口。

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


答案 2

可扩展的注释将有效地增加指定和维护另一个类型系统的负担。这将是一个相当独特的类型系统,因此您不能简单地应用OO类型范例。

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

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

您想知道给定的注释是否属于某个类别吗?

试试这个:

@Target(ElementType.ANNOTATION_TYPE)
public @interface Category {
    String category();
}

@Category(category="validator")
public @interface MyFooBarValidator {

}

如您所见,您可以使用提供的功能轻松地对注释进行分组和分类,而不会造成不必要的痛苦。

因此,KISS是没有将元类型类型系统引入Java语言的原因。

[附注编辑]

我使用 String 只是为了演示,并查看开放式元注释。对于您自己的给定项目,您显然可以使用类别类型的枚举,并为给定的注释指定多个类别(“多重继承”)。请注意,这些值完全是伪造的,仅用于演示目的:

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

}


推荐