The following compiles fine in my Eclipse:
final int j = 1/0;
// compiles fine!!!
// throws ArithmeticException: / by zero at run-time
Java prevents many "dumb code" from even compiling in the first place (e.g. "Five" instanceof Number
doesn't compile!), so the fact this didn't even generate as much as a warning was very surprising to me. The intrigue deepens when you consider the fact that constant expressions are allowed to be optimized at compile time:
public class Div0 {
public static void main(String[] args) {
final int i = 2+3;
final int j = 1/0;
final int k = 9/2;
}
}
Compiled in Eclipse, the above snippet generates the following bytecode (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
}
As you can see, the i
and k
assignments are optimized as compile-time constants, but the division by 0
(which must've been detectable at compile-time) is simply compiled as is.
javac 1.6.0_17
behaves even more strangely, compiling silently but excising the assignments to i
and k
completely out of the bytecode (probably because it determined that they're not used anywhere) but leaving the 1/0
intact (since removing it would cause an entirely different program semantics).
So the questions are:
- Is
1/0
actually a legal Java expression that should compile anytime anywhere?- What does JLS say about it?
- If this is legal, is there a good reason for it?
- What good could this possibly serve?