2017-04-17 79 views
3

似乎可以在Java中的注释声明中声明字段和枚举。例如,javac编译这个:在注释声明中定义枚举和字段有什么意义?

@interface ClassPreamble { 
    public enum AnEnum { 
     Value; 
    } 
    String aField = ""; 

    String author(); 
    String date(); 
    String currentRevision() default ""; 
    String lastModified() default "N/A"; 
    String lastModifiedBy() default "N/A"; 
    // Note use of array 
    String[] reviewers(); 
} 

定义注释声明中枚举和字段的含义/用处是什么?

感谢

+0

这在例如解释[官方文档](https://docs.oracle.com/javase/tutorial/java/annotations/declaring.html)。 –

+0

@OliverCharlesworth请仔细阅读我的问题。我知道注释如何有用。我只是不知道在注释声明中定义字段和枚举是多么有用。 – mljrg

+0

是的,我只是说这个链接举了一个例子。 –

回答

1

Java注解只是继承接口java.lang.annotation.Annotation(*),并且是由编译器经特殊处理,在一定程度上,但编译器不会阻止你做一切的接口中是合法的。它甚至可以是有用的(参见本答案底部的JLS示例)。

(*)虽然手动扩展Annotation的接口并没有定义注释类型(来源:javadocAnnotation.java

你的注释ClassPreamble实际上是interface ClassPreamble extends java.lang.annotation.Annotation(编译它来看一看)。

在接口中声明一个枚举是合法的。 在接口中声明一个字段是合法的:它将隐式地公共static final。

$ cat Funny.java 
interface Funny { 
    public enum AnEnum { One, Two } 
    String aField = ""; 
} 

$ javac Funny.java 

$ javap -c Funny.class 
Compiled from "Funny.java" 
interface Funny extends java.lang.annotation.Annotation { 
    public static final java.lang.String aField; 

} 

$ javap -c Funny\$AnEnum.class | head 
Compiled from "Funny.java" 
public final class Funny$AnEnum extends java.lang.Enum<Funny$AnEnum> { 
    public static final Funny$AnEnum One; 

    public static final Funny$AnEnum Two; 

    public static Funny$AnEnum[] values(); 
    Code: 
     0: getstatic  #1     // Field $VALUES:[LFunny$AnEnum; 
     3: invokevirtual #2     // Method "[LFunny$AnEnum;".clone:()Ljava/lang/Object; 
... 

我不确定“这种结构的含义是什么?”有一个很好的答案。我猜这是作为设计选择以这种方式实现的:无论注释是否编码为接口的字节码,JVM知道如何处理,所以它们不需要过多地修改JVM本身(如果有的话)它在编译时和运行时允许使用所需的特性,并且不会造成危害(或者不是?)。

编辑:从Java Language Specification section 9.6 about annotations 2点提取(属于关于接口第9章):

注释类型声明指定一个新的注释类型,一类特殊的接口类型。为了将注释类型声明与正常的接口声明区分开来,关键字接口前面有一个at符号(@)。

[...]

用于注释的类型声明的语法允许除方法声明其他元素声明。例如,一个可能选择声明一个嵌套枚举结合使用与注释类型:

@interface Quality { 
    enum Level { BAD, INDIFFERENT, GOOD } 
    Level value(); 
} 
+0

是的,它似乎是一个接口编译器基础结构被黑客攻击来支持注释,并且黑客入侵仍然是不完整的。例如,如果您执行'Level value()default INDIFFERENT',那么'Quality'会失败,并显示编译错误,这似乎是应该支持的完全有效的用法。事情是,我很好奇,因为我从来没有见过这样的注释声明的例子。我已经怀疑这是一个“黑客”案件,并会接受你的答案。 – mljrg

+0

'级别值()默认Level.INDIFFERENT;'是正确的,接受 –

+0

好吧,不记得试试看。很高兴知道! – mljrg

相关问题