为啥在注释中禁止 null 作为默认值?

Posted

技术标签:

【中文标题】为啥在注释中禁止 null 作为默认值?【英文标题】:Why is null forbidden as default value in annotations?为什么在注释中禁止 null 作为默认值? 【发布时间】:2019-07-06 16:12:26 【问题描述】:

根据Annotation default "null" value,注释中禁止空值作为默认值。 我想知道为什么。这是什么原因?

【问题讨论】:

对我来说似乎是任意的。这就是我问的原因。 限制很明确:due to "grammar"... 和(对我来说)...这是有道理的,因为 default 被使用/想要克服一些空/空值,不是吗? ..和! Object foo(); 已经达到了与Object foo() default null; 相同的效果...它是“null,当从注释中省略时”!?;) 【参考方案1】:

请注意,null 不仅不支持作为默认值,也不支持作为注释值一般

JLS §9.7.1 指定:

如果元素类型与元素值不相称,则为编译时错误。当且仅当满足以下条件之一时,元素类型 T 与元素值 V 相称:

T 是数组类型 E[],并且:

如果VConditionalExpressionAnnotation,则VE 相称;或

如果V 是一个ElementValueArrayInitializer,那么V 包含的每个元素值都与E 相称。

ElementValueArrayInitializer 类似于普通数组初始化程序 (§10.6),除了 ElementValueArrayInitializer 在语法上可能包含注释以及表达式和嵌套初始化程序。但是,嵌套初始化器在 ElementValueArrayInitializer 中在语义上是不合法的,因为它们永远不会与注释类型声明中的数组类型元素相称(不允许嵌套数组类型)。

T 不是数组类型,V 的类型与T 的赋值兼容(§5.2),并且: 如果T 是基本类型或String,则V 是常量表达式(§15.29)。 如果TClassClass (§4.5) 的调用,则V 是一个类文字(§15.8.2)。 如果 T 是枚举类型 (§8.9),则 V 是枚举常量 (§8.9.1)。 V 不是 null

最后一个禁止null 的项目符号看起来很随意,但即使没有那个项目符号,null 也不是合法值,因为它既不是常量表达式、类文字也不是枚举常量。

所以最后一个项目符号只是明确表明这不是疏忽。

当注释被添加到语言中时,编译时常量的定义已经存在,包括存储它们的字节码格式。类字面量也在语法上定义,但与常量不同。但是有了JDK-4662563,它们的字节码格式就等同于同一版本中的其他常量。所以对类文字的支持对于注解也是很自然的。

唯一为注释支持添加的功能是对枚举常量的引用和数组的存储格式。两者都立即证明了它们作为注解定义本身所需的内置注解的有用性,@RetentionTarget 都使用枚举常量,而后者也使用数组。

因此,null 并未从合法构造集中删除,它从未被添加。考虑的用例既不直接也不自然。

This answer 表明添加对null 的支持的建议最初已被考虑用于类型注释提案(另请参见the archive link),此时提出反对意见。众所周知,Java 8 引入了类型注解,而不支持 null(其他建议,如可重复注解,使其成为语言)。

【讨论】:

感谢您对这个问题的广泛回答,并提供所有背景和链接。当我问这个问题时,这就是我正在寻找的东西。你的回答表明这个决定不是武断的。

以上是关于为啥在注释中禁止 null 作为默认值?的主要内容,如果未能解决你的问题,请参考以下文章

golang函数中的参数为啥不支持默认值

我可以将 null 设置为 Spring 中 @Value 的默认值吗?

为啥我从 Dapper 返回的对象具有 null 和默认属性值?

prisma:为啥我不能将“null”设置为可空列的默认值?

如何为注释类型编码可选的默认注释值

MySQL中没有默认值Vs NULL Vs 0作为文本和整数字段的默认值[关闭]