在Java中调试时,我使用了一个负数长度来初始化一个新的字符串数组。即:
String[] arr = new String[-1];
令我惊讶的是,编译器没有对此发出任何抱怨。 谷歌搜索也没有找到相关答案。有人可以为这个问题提供一些线索吗?
非常感谢!
在Java中调试时,我使用了一个负数长度来初始化一个新的字符串数组。即:
String[] arr = new String[-1];
令我惊讶的是,编译器没有对此发出任何抱怨。 谷歌搜索也没有找到相关答案。有人可以为这个问题提供一些线索吗?
非常感谢!
原因是JLS允许这样做,如果编译器将其标记为编译错误,则会拒绝有效的Java代码。
这在JLS 15.10.1中有明确说明。以下是相关摘录:
"…… 如果任何DimExpr表达式的值小于零,则抛出NegativeArraySizeException异常。"
如果Java编译器将此代码标记为错误,则该指定行为无法在该特定代码中发生。
此外,我找不到任何授权编译器拒绝像-1
这样的编译时常量表达式的“显而易见的错误”情况的文本。 (而且谁能说这真的是一个错误?)
下一个问题当然是“为什么JLS允许这样做?”
您需要问Java设计者。但是我可以想到一些(大多数)合理的原因:
最初被忽视,并且没有强烈的理由修复它。 (注意,修复它会破坏源代码兼容性。)
它被认为是太不寻常/边缘的情况,不值得处理。
这可能会给编写源代码生成器的人带来问题。 (想象一下,必须编写代码来评估编译时常量表达式,以便您不会生成非可编译代码。使用当前的JLS规范,您可以简单地生成带有“错误”大小的代码,并在执行该代码时处理异常(或不处理)。)
也许有人计划在Java中添加"unarrays" :-)
其他答案建议编译器可以或应该“标记”这种情况。如果“标记”指输出警告信息,则 JLS 明确允许这样做。然而,编译器是否应该这样做还有争议。一方面,如果上述代码是错误编写的,则标记出这个错误很有用。另一方面,如果它不是一个错误(或者这个“错误”不相关),那么警告就是噪音,甚至更糟。无论哪种情况,这都需要与各自编译器的维护者进行讨论。
DimExpr
不允许负的编译时常量,所以指定的行为不会发生。 - Marko Topolniknew String [<negative_compile_time_constant>]
?因为像 int i = -1; new String [i]
这样的代码已经超出了编译时常量的范围。 - Marko Topolniknew String[-1]
被标记为编译错误,那么new String[-1]
就不可能抛出异常。JLS规定它应该抛出异常...没有任何关于编译时常量表达式的限定。这是我对JLS的理解。无论如何,这是一个愚蠢的争论,因为事实上这不是一个编译错误,而且JLS中也没有说它应该是一个编译错误。 - Stephen CNegativeArraySizeException
。
我已经使用我的编译器做了一些快速实验,发现它对这种情况非常放松。它没有对定值表达式中的整数除零、定值索引处超出数组边界等问题发出警告。
由此我得出结论:在这里的一般模式是信任程序员。
编译器只负责检查语言的语法,而不是您代码的语义含义。 因此,如果您的代码中没有语法错误,编译器不会报错,这是合理的。
在Java中,数组是在运行时分配的,这是完全可以的。如果它在编译时分配,则编译器如何检查以下代码?
// runtime pass the length, with any value
void t(int length) {
String[] stirngs = new String[length];
}
当将负值作为长度传递给构造数组时,运行时异常将被抛出。
public class Main {
public static void main(String[] args) {
String[] v = new String[-1];
}
}
有错误:
Exception in thread "main" java.lang.NegativeArraySizeException
at Main.main(Main.java:5)
if(true) { System.out.println("true"); } else { System.out.println("dead code"); }
这样的语义死代码却不一定会被检测到。只有集成开发环境才会标记为警告。 - Pau Kiat WeeJava编译器以一个整数作为数组的长度,它可以是变量或者编译时常量。当数组被创建时,它的长度就确定了并且在创建之后不再改变。
编译器应该标记负的编译时常量作为数组的长度,但实际上并没有这么做。如果长度是负数,那么你将在运行时得到一个NegativeArraySizeException异常。
String[] arr = new String[someNumberThatMightOrMightNotBeNegative];
- 挑战你在编译时检查它!请注意“that”的含义。 - Izkata