Java “new String[-1]” 通过编译。怎么会这样?

2022-09-01 17:38:36

在Java中摆弄时,我初始化了一个长度为负值的新字符串数组。即 -

String[] arr = new String[-1];

令我惊讶的是,编译器并没有抱怨它。谷歌搜索没有带来任何相关的答案。谁能对这个问题有所了解?

非常感谢!


答案 1

原因是JLS允许这样做,而将其标记为编译错误的编译器将拒绝有效的Java代码。

它在 JLS 15.10.1 中指定。以下是相关代码段:

"...如果任何 DimExpr 表达式的值小于零,则会抛出一个 NegativeArraySizeException。

现在,如果Java编译器将代码标记为错误,则指定的行为就不会发生...在该特定代码中。

此外,我找不到任何文本可以“授权”编译器在涉及编译时常量表达式的“明显错误”情况下拒绝这一点,例如.(谁能说这真的是一个错误?-1


当然,下一个问题是“为什么JLS允许这样做?

你需要问问Java设计师。然而,我可以想到一些(大多数)合理的理由:

  • 这最初被忽视了,并且没有强有力的理由来修复它。(请注意,修复它会破坏源代码兼容性。

  • 它被认为太不寻常/边缘情况不值得处理。

  • 它可能会给编写源代码生成器的人带来问题。(想象一下,必须编写代码来计算编译时常量表达式,以便不生成不可编译的代码。使用当前的JLS规范,您可以简单地生成具有“坏”大小的代码,并在代码被执行时处理异常(或不处理)。

  • 也许有人计划将“unarrays”添加到Java中:-)


其他答案表明编译器可以/应该“标记”这种情况。如果“标记”意味着输出警告消息,那么JLS肯定是允许的。但是,编译器是否应该这样做是有争议的。一方面,如果上面的代码是错误地编写的,那么标记该错误将是有用的。另一方面,如果它不是一个错误(或者“错误”不相关),那么警告将是噪音,甚至更糟。无论哪种方式,您都需要与相应编译器的维护者讨论这个问题。


答案 2

我看不出为什么这不能在编译时标记出来(至少作为警告),因为这在执行时无条件地抛出NealArraySizeException

我已经用我的编译器做了一些快速的实验,对这种事情似乎非常放松。它不会发出有关常量表达式中的整数除以零,具有常量索引的越界数组访问等的警告。

由此我得出结论,这里的一般模式是信任程序员。