以下在我的 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
(必须've been detected at compile-time) 只是按原样编译。
javac 1.6.0_17
的行为更加奇怪,它静默编译,但完全从字节码中删除了对 i
和 k
的赋值(可能因为它确定它们没有在任何地方使用)但保持 1/0
完整(因为删除它会导致完全不同的程序语义)。
所以问题是:
1/0
真的是合法的Java 表达式,应该随时随地编译吗?- JLS 对此有何评论?
- 如果这是合法的,是否有充分的理由?
- 这可能有什么好处?
最佳答案
Is
1/0
actually a legal Java expression that should compile anytime anywhere?
是的。
What does JLS say about it?
没有什么特别的……除了说除以零会导致运行时异常。但是,JLS 在以下定义中承认运行时异常的可能性:
"A compile-time constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following: ..."
(添加了重点。)因此以下内容无法编译:
switch(i) {
case 1:
case 1 + 1:
case 1 / 0: // compilation error.
}
If this is legal, is there a good reason for it?
好问题。我想这是一种抛出 ArithmeticException
的方法,尽管这不是一个合理的理由。以这种方式指定 Java 的一个更可能的原因是避免 JLS 和编译器中不必要的复杂性来处理很少会咬人的边缘情况。
但这一切都是凭空而来的。事实上,1/0
是有效的 Java 代码,任何 Java 编译器都不应该将其标记为编译错误。 (如果有一个编译器开关可以关闭它,Java 编译器发出警告是合理的。)
关于java - 1/0 是合法的 Java 表达式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2934063/