【问题标题】:Java annotations - Identifier or TypeNameJava 注释 - 标识符或类型名称
【发布时间】:2013-06-08 05:42:38
【问题描述】:

Java 语言规范声明a normal annotation 的格式为

NormalAnnotation:
@ TypeName (ElementValuePairsopt)

A single-element annotation 的格式为:

SingleElementAnnotation:
@标识符元素值

我不明白,为什么会出现这种不一致,为什么普通注解是TypeName 而单个元素注解是Identifier?我相信对Identifier 的引用可能是规范中的错误,因为标识符不合格,而 javac 接受合格的 AnnotationDeclarations,无论是普通注释还是单元素注释。

【问题讨论】:

    标签: java annotations language-lawyer


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      单元素注解表示为:

      SingleElementAnnotation:
          @ TypeName ( ElementValue )
      

      【讨论】:

        【解决方案3】:

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

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

        Identifier:标识符用于命名或描述一个变量或一个类。在正确的上下文中,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
        

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

        【讨论】:

          【解决方案4】:

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

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

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

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

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

          标识符必须是在 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() 是允许的。我可以使用的每个编译器都允许后者。这使得几乎每个人的区别都没有实际意义。

          【讨论】:

            猜你喜欢
            • 2014-11-18
            • 1970-01-01
            • 2020-05-26
            • 2016-12-14
            • 2016-07-17
            • 2010-10-16
            • 2019-04-07
            • 2022-12-16
            相关资源
            最近更新 更多