1/0是合法的Java表达式吗?

以下在我的Eclipse中可以正常编译:

final int j = 1/0;

// compiles fine!!!

// throws ArithmeticException: / by zero at run-time

Java甚至一开始就阻止了许多“愚蠢的代码”的编译(例如"Five" instanceof

Number,没有编译!),所以它甚至没有产生像警告一样多的事实,这令我感到非常惊讶。当您考虑允许在编译时优化常量表达式这一事实时,这种兴趣就加深了:

public class Div0 {

public static void main(String[] args) {

final int i = 2+3;

final int j = 1/0;

final int k = 9/2;

}

}

上面的代码段在Eclipse中编译,生成了以下字节码(javap -c Div0

Compiled from "Div0.java"

public class Div0 extends java.lang.Object{

public Div0();

Code:

0: aload_0

1: invokespecial #8; //Method java/lang/Object."<init>":()V

4: return

public static void main(java.lang.String[]);

Code:

0: iconst_5

1: istore_1 // "i = 5;"

2: iconst_1

3: iconst_0

4: idiv

5: istore_2 // "j = 1/0;"

6: iconst_4

7: istore_3 // "k = 4;"

8: return

}

如您所见,ik分配被优化为编译时常量,但是除法0(必须在编译时可检测到)被简单地按原样编译。

javac

1.6.0_17它的行为甚至更奇怪,它会静默地编译,但会删除字节码中的分配,i并将其k完全从字节码中删除(可能是因为它确定未在任何地方使用它们),但保持1/0原样(因为删除它会导致完全不同的程序语义)。

所以问题是:

  • 1/0实际上应该编译随时随地法律Java表达式?

    • JLS对此有何评论?

  • 如果这是合法的,那么有充分的理由吗?

    • 这可能有什么好处?

回答:

1/0实际上应该编译随时随地法律Java表达式?

是。

JLS对此有何评论?

除了说被零除会导致运行时异常外,没有什么特别的。但是,JLS在以下定义中承认存在运行时异常的可能性:

“编译时常量表达式是表示原始类型或String的值的表达式,该值 并且仅使用以下内容组成:…”

(添加了强调。)因此以下内容将无法编译:

switch(i) {

case 1:

case 1 + 1:

case 1 / 0: // compilation error.

}

如果这是合法的,那么有充分的理由吗?

好问题。我想这是一种抛出的方式,ArithmeticException尽管这几乎不是合理的理由。用这种方式指定Java的更可能的原因是避免JLS和编译器处理不必要的情况而造成不必要的复杂性。

但这一切都是靠。事实是,这1/0是有效的Java代码,并且任何Java编译器都不应将其标记为编译错误。(如果有编译器开关将其关闭,则对于Java编译器发出警告是合理的。)

以上是 1/0是合法的Java表达式吗? 的全部内容, 来源链接: utcz.com/qa/419584.html

回到顶部