@Retention(RUNTIME) @Target({PACKAGE,FIELD,METHOD,TYPE,PARAMETER})
public @interface XmlJavaTypeAdapter {
Class type() default DEFAULT.class;
static final class DEFAULT {}
}
public @interface MyAnnotation {
public static final String DEFAULT_PREFIX = "__class-name-here__ default";
...
public String prefix() default DEFAULT_PREFIX;
}
然后在我的代码中,我会执行如下操作:
if (myAnnotation.prefix().equals(MyAnnotation.DEFAULT_PREFIX)) { ... }
对于类,我只需要定义一个标记类,不幸的是,你不能用常量来表示,所以你需要做如下的事情:
public @interface MyAnnotation {
public static Class<? extends Foo> DEFAULT_BAR = DefaultBar.class;
...
Class<? extends Foo> bar() default DEFAULT_BAR;
}
您的DefaultFoo类将只是一个空实现,以便代码可以执行以下操作:
if (myAnnotation.bar() == MyAnnotation.DEFAULT_BAR) { ... }
7条答案
按热度按时间vmdwslir1#
我不知道为什么,但JLS非常清楚:
默认元素的定义为:
不幸的是,我不断发现新的语言特性(Enums和现在的Annotations)在您不满足语言规范时会显示非常无用的编译器错误消息。
编辑:稍微搜索一下JSR-308,发现了以下内容,他们主张在这种情况下允许空值:
我们注意到对这项建议可能有一些反对意见。
这项提议没有使以前不可能的事情成为可能。
程序员定义的特殊值提供了比null更好的文档,null可能意味着“无”、“未初始化”、null本身等等。
这个提议更容易出错,忘记检查null比忘记检查显式值要容易得多。
这个提议可能会使标准习惯用法变得更加冗长。目前只有注解的用户需要检查它的特殊值。根据这个提议,许多处理注解的工具将不得不检查字段的值是否为空,以免抛出空指针异常。
我认为只有最后两点与“为什么不在第一个地方做它”相关。最后一点当然提出了一个很好的观点-注解处理器永远不必担心它们会在注解值上得到空值。我倾向于认为,注解处理器和其他类似框架代码的工作更多地是必须进行这种检查,以使开发人员的代码更清晰,而不是相反,但这肯定会使改变它变得很难。
zd287kbt2#
试试这个
它不需要一个新的类,而且在Java中它已经是一个没有任何意义的关键字。
mlnl4t2r3#
这似乎是非法的,虽然JLS在这一点上非常模糊。
我绞尽脑汁地试图想出一个现有的注解,它具有注解的Class属性,并从JAXB API中记住了这个注解:
您可以看到他们是如何定义一个伪静态类来保存null的等价物的。
不愉快。
fquxozlt4#
似乎还有另一种方法可以做这件事。
我也不喜欢这样,但可能有用。
所以基本上你创建了一个空的数组,这似乎允许一个默认值。
13z8s7eq5#
如前所述,Java语言规范不允许注解缺省值为空值。
我倾向于在注解定义的顶部定义
DEFAULT_VALUE
常量,类似于:然后在我的代码中,我会执行如下操作:
对于类,我只需要定义一个标记类,不幸的是,你不能用常量来表示,所以你需要做如下的事情:
您的
DefaultFoo
类将只是一个空实现,以便代码可以执行以下操作:希望这个有用。
qqrboqgw6#
正如其他人所说的,有一条规则规定null不是Java中有效的默认值。
如果字段的可能值数量有限,那么解决这个问题的一个方法是将字段类型设置为自定义枚举,该枚举本身包含到null的Map。例如,假设我有以下注解,我希望为它设置默认null:
正如我们已经确定的,这是不允许的。我们可以做的是定义一个枚举:
并按如下方式更改注解:
这样做的主要缺点(除了需要枚举可能的值之外)是,您现在已经将值 Package 在一个枚举中,因此您需要调用枚举上的属性/getter来获取值。
k4emjkb17#
不,Java语言规范没有将
null
文字/值定义为常量表达式。在定义注解类型元素的可能默认值时,规范规定了以下内容:
如果元素的类型与指定的默认值不相称(参见9.7节),这是一个编译时错误。
为了解释这意味着什么
如果元素类型与元素值不相称,则为编译时错误。当且仅当下列条件之一为真时,元素类型T与元素值V相称:
T
是数组类型E[]
,并且:T
不是数组类型**,并且V
的类型与T
、和是赋值兼容的(参见5.2节):T
是一个基元类型或String
,那么V
是一个常量表达式(参见15.28节)。T
是Class
或者是Class
的调用(参见4.5节),那么V
是一个类常量(参见15.8.2节)。T
是一个枚举类型(参见8.9节),那么V
是一个枚举常量(参见8.9.1节)。因此,这里的元素类型
Class<? extends Foo>
与默认值不相称,因为默认值是null
。