【发布时间】:2010-05-29 06:22:37
【问题描述】:
以下在我的 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中编译,上面的sn -p生成如下字节码(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 对此有何评论?
- 如果这是合法的,是否有充分的理由?
- 这可能有什么好处?
【问题讨论】:
-
Downvoter:想解释一下这个问题如何不清楚或没有用处?因为我以后会有更多的问题,所以我想知道在哪里可以改进。
-
@polygenelubricants:老实说,我不知道这些细节是否会让你成为更好的程序员。 25 年以上的编程经验,除了来自 “语言律师” POV 和“Java Puzzlers” POV(尽管 Java 谜题者比这更好),我认为这有一个非零概率只是头发分裂和浪费时间(在这里说实话:大多数在这里回答的专业开发人员可能都不知道,而且在他们不知道这个 Java 细节的情况下,这可能不会以任何方式伤害他们)。我,一方面,不想看到这样的问题出没:(
-
另一种说法是:对我来说,一直花时间挑剔/回答/评论这样的问题(显然你将来会有更多类似的问题)可以花在学习上,比如说,一点点 Lisp ……那真的会让你成为一个更好的程序员。
-
@Webinator 另一个观点,来自另一个几十年的程序员。很久以前,一个我非常尊敬的人告诉我,如果我不知道至少三种破坏工具的方法,我还没有真正学会使用它。当我开始编程时,我将这个比喻扩展到适用于边缘条件、奇怪的行为,甚至是一些吹毛求疵的事情。编程就是管理细节。
-
@Webinator:比起软件工程师,我更像是一名计算机科学家,所以像这样的语言问题让我非常感兴趣。我不仅关心如何编写更好的程序。我还关心如何设计更好的语言。
标签: java divide-by-zero