В моем 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, которое должно скомпилироваться в любое время в любом месте?
- Если это законно, есть ли для этого веская причина?
- Что хорошего это может послужить?