8

Java 语言规范声明普通注解格式为

NormalAnnotation
  @TypeName ( ElementValuePairs opt ) _

单元素注释的格式为:

SingleElementAnnotation :
  @Identifier ( ElementValue )

我不明白,为什么会出现这种不一致,为什么普通注释 aTypeName和单个元素注释 a Identifier?我相信对的引用Identifier可能是规范中的错误,因为 Identifier 不合格,并且 javac 接受了合格的 AnnotationDeclarations,用于普通注释和单元素注释。

4

4 回答 4

7

对 的引用Identifier是规范中的一个错误,因为标识符不能被限定(你可以写@java.lang.SuppressWarnings("unchecked")java.lang.SuppressWarnings不是合法的标识符)。Javac 接受符合条件的 AnnotationDeclarations,适用于普通注解和单元素注解。这个错误似乎是最近才出现的;旧版本的 JLS 没有这个问题。

于 2013-07-27T05:37:10.940 回答
1

我认为语法文档中有错误。单个注释元素和标记注释是普通注释的简写

您还可以查看 Java 1.5/1.6 规范:http ://docs.oracle.com/javase/specs/jls/se5.0/html/interfaces.html#9.7

单元素注释表示为:

SingleElementAnnotation:
    @ TypeName ( ElementValue )
于 2013-08-02T14:09:27.013 回答
0

教程说明标识符和类型名称是两个不同的东西。从编程的角度来看,它们不是。但从逻辑的角度来看,它们可能是正确的类比。

TypeName开始:数据类型(不包括原始类型)和类通常具有多个方法和/或属性。所以在某种程度上,TypeName有点像类或数据类型的名称,它就是这样。

On to Identifier:标识符用于命名或描述一个变量或一个类。在正确的上下文中,标识符可以与单个事物相关联,例如 int 值,而 TypeName 可以在一个类中表示 int 和 String。

int Identifier = 90; //Identifier represents an int value
class TypeName{
int i;
String s;
} //TypeName represents an int value and a String
TypeName MyNew = new TypeName(); //MyNew references to a TypeName, holding more
//than one value

这是一个非常谨慎的逻辑,所以如果你乍一看这个逻辑没有意义,作者可能为了清楚起见而更改了名称,让它们有点不同。但无论作者如何称呼它们,它们都是同一个东西,只是措辞不同。

于 2013-07-29T18:41:52.867 回答
0

这是一个语义问题(以及相当迂腐的语义)。

考虑一个NormalAnnotation,例如@SuppressWarnings(value={"foo","bar")),其中SuppressWarnings(TypeName)解析为具有名为 的成员的注释类value

现在考虑一个SingleElementAnnotation,例如@SuppressWarnings({"foo","bar"))。Identifier ( SuppressWarnings)接口的名称,但没有任何内容表明应将一个参数分配给value

因此,您不能直接将该字符序列解析为NormalAnnotation; 它没有正确格式的ElementValuePairs. 但是,如果您value=在左括号和参数开头之间插入 , ,那么您将得到可解析为 NormalAnnotation 的内容。

MarkerAnnotation 也是如此。它缺少 NormalAnnotation 所需的括号。

Identifier 必须是在 NormalAnnotation 中使用时会产生 TypeName 的值。

NormalAnnotation 对其有很多限制,例如:

如果 TypeName 未命名在使用注释时可访问的注释类型(第 6.6 节),则这是编译时错误。

直到 SingleElementAnnotation 或 MarkerAnnotation 转化为 NormalAnnotation 之前,SuppressWarnings它只是一个 Identifier,只需要符合Identifier的定义即可。请注意,TypeNames 可以被限定,例如java.lang.SuppressWarnings,但 Identifiers 不能。

我相信其意图是 MarkerAnnotation 和 SingleElementAnnotation 应该使用简单名称(标识符)而不是完全限定名称(类型名称)。所以从技术上讲@Override是可以的,@java.lang.Override是不正确的,但@java.lang.Override()会被允许。我可以使用的每个编译器都允许后者。这使得几乎每个人的区别都没有实际意义。

于 2013-08-02T05:16:36.307 回答