Java 爪哇语;新字符串[-1]”;通过编译。怎么会?

Java 爪哇语;新字符串[-1]”;通过编译。怎么会?,java,arrays,compilation,Java,Arrays,Compilation,在Java中四处摆弄时,我初始化了一个长度为负的新字符串数组。 i、 e.- 令我惊讶的是,编译器并没有对此抱怨。 谷歌没有给出任何相关的答案。有人能解释一下这件事吗 非常感谢 原因是JLS允许这样做,而将其标记为编译错误的编译器将拒绝有效的Java代码 它在中指定。以下是相关片段: “…如果任何DimExpr表达式的值小于零,则抛出NegativeArraySizeException。” 现在,如果Java编译器将代码标记为错误,那么指定的行为将不会发生。。。在特定的代码中 此外,在涉及编译时

在Java中四处摆弄时,我初始化了一个长度为负的新字符串数组。 i、 e.-

令我惊讶的是,编译器并没有对此抱怨。 谷歌没有给出任何相关的答案。有人能解释一下这件事吗


非常感谢

原因是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.NegativeArraySizeException
String[]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)