Следующие компилируются в моем 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
}
Как вы можете видеть, назначения i
и k
оптимизируются как константы времени компиляции, но деление на 0
(которое должно быть обнаружено во время компиляции) просто компилируется как есть.
javac 1.6.0_17
ведет себя еще более странно, компиляция молча, но исключая назначения i
и k
полностью из байт-кода (вероятно, потому, что он определил, что они нигде не используются), но оставляя 1/0
неповрежденным (поскольку удаление его приведет к совершенно другой семантике программы).
Итак, вопросы:
- Является ли
1/0
законным выражением Java, которое должно компилироваться в любое время в любом месте?- Что говорит JLS об этом?
- Если это законно, есть ли веская причина для этого?
- Какая польза от этого может случиться?