Java 爪哇语;新字符串[-1]”;通过编译。怎么会?
在Java中四处摆弄时,我初始化了一个长度为负的新字符串数组。 i、 e.- 令我惊讶的是,编译器并没有对此抱怨。 谷歌没有给出任何相关的答案。有人能解释一下这件事吗Java 爪哇语;新字符串[-1]”;通过编译。怎么会?,java,arrays,compilation,Java,Arrays,Compilation,在Java中四处摆弄时,我初始化了一个长度为负的新字符串数组。 i、 e.- 令我惊讶的是,编译器并没有对此抱怨。 谷歌没有给出任何相关的答案。有人能解释一下这件事吗 非常感谢 原因是JLS允许这样做,而将其标记为编译错误的编译器将拒绝有效的Java代码 它在中指定。以下是相关片段: “…如果任何DimExpr表达式的值小于零,则抛出NegativeArraySizeException。” 现在,如果Java编译器将代码标记为错误,那么指定的行为将不会发生。。。在特定的代码中 此外,在涉及编译时
非常感谢 原因是JLS允许这样做,而将其标记为编译错误的编译器将拒绝有效的Java代码 它在中指定。以下是相关片段: “…如果任何DimExpr表达式的值小于零,则抛出NegativeArraySizeException。” 现在,如果Java编译器将代码标记为错误,那么指定的行为将不会发生。。。在特定的代码中 此外,在涉及编译时常量表达式(如
-1
)的“明显错误”情况下,我找不到任何文本“授权”编译器拒绝此操作。(谁能说这真的是个错误?)
当然,下一个问题是“为什么JLS允许这样做?” 您需要询问Java设计人员。然而,我可以想出一些(大部分)合理的理由:
- 这一点最初被忽略了,没有足够的理由来修复它。(注意,修复它会破坏源代码兼容性。)
- 这被认为是非常不寻常的/边缘案件,不值得处理
- 这可能会给编写源代码生成器的人带来问题。(想象一下,为了不生成不可编译的代码,必须编写代码来计算编译时常量表达式。使用当前的JLS规范,您只需生成大小为“坏”的代码,并在执行代码时处理异常(或不处理异常)
- 也许有人计划在Java中添加“unarray:-)
其他答案表明编译器可以/应该“标记”这种情况。如果“标记”意味着输出警告消息,那么JLS肯定允许这样做。然而,编译器是否应该这样做还有争议。一方面,如果上面的代码是错误编写的,那么将该错误标记出来将非常有用。另一方面,如果不是错误(或者“错误”不相关),那么警告将是噪音,或者更糟。无论哪种方式,这都是您需要与相应编译器的维护人员讨论的问题。Java编译器将整数作为数组的长度。它可以是变量或编译时常量。数组的长度是在创建数组时确定的。创建后,其长度是固定的
编译器应该将负编译时常量标记为数组的长度。但事实并非如此。如果长度为负数,则在运行时会出现NegativeArraySizeException。我看不出为什么不能在编译时标记它(至少作为警告),因为这样做 我已经用我的编译器做了一些快速的实验,对于这类事情,它似乎出人意料地放松了。它不会发出关于常量表达式中整数除以零、使用常量索引进行越界数组访问等警告
由此我得出结论,这里的一般模式是信任程序员。编译器只负责检查语言语法,而不负责检查代码的语义。 因此,编译器没有抱怨错误是合理的,因为代码中根本没有语法错误 在Java中,数组是在运行时分配的,这是绝对正确的。如果它是在编译时分配的,那么编译器如何检查以下代码
// runtime pass the length, with any value
void t(int length) {
String[] stirngs = new String[length];
}
将负值作为长度传递给construct数组时,将引发运行时异常
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)
当然,下一个问题是‘JLS为什么允许这样做?’指定的行为不能发生并不是因为
DimExpr
@MarkoTopolnik不允许负编译时常数——您的评论已被注意到,但我不同意。您是否声称“指定行为”的唯一方法是在执行新字符串[]
时,即将发生的情况?因为代码像inti=-1;新字符串[i]代码>已经超出编译时常量的范围。不,我没有。我声明,如果newstring[-1]
被标记为编译错误,那么newstring[-1]
无法引发异常。JLS声明它应该抛出一个异常。。。没有任何关于编译时常量表达式的限制。这就是我对JLS的理解。无论如何,这是一个愚蠢的诡辩,因为事实上这不是一个编译错误,JLS中没有任何东西说这应该是一个编译错误。编译器不检查数组的大小,但是如果负数的大小抛出java.lang.NegativeArraySizeExceptionString[]arr=new String[Somenumberthat MightMightMightMightNotBenegative];
-在编译时检查一下,我敢说!@Izkata-我使用了Eclipse,但它仍然对此非常满意(即-没有警告或任何东西)@TomTeman您误解了。编译器必须实际运行代码以确定数字是否为负数,即使如此,它也必须尝试所有可能的代码路径,包括所有可能的输入,以最终确定该数字是否为负数。这根本是不可能的。因此语言设计师决定在运行时进行检查,因为这将捕获问题中的版本和我上面评论中的版本。Lol..简单回答..切换到C#和死代码检测呢?这是语法还是语义?死代码是编译器错误。Java中还有许多其他此类功能,比如检查每个代码路径是否指向return语句。没有返回的方法肯定会被co检测到
Exception in thread "main" java.lang.NegativeArraySizeException
at Main.main(Main.java:5)