java - 1/0 是合法的 Java 表达式吗?

标签 java divide-by-zero

以下在我的 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

}

如您所见,ik 赋值被优化为编译时常量,但除以 0(必须've been detected at compile-time) 只是按原样编译。

javac 1.6.0_17 的行为更加奇怪,它静默编译,但完全从字节码中删除了对 ik 的赋值(可能因为它确定它们没有在任何地方使用)但保持 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/

相关文章:

java - ffmpeg,stderr 上的信息转储

java - 从通用通配符引用调用方法

sql - Redshift 除以零谜题

java - 什么是NullPointerException,我该如何解决?

java - 当源附件不可修改时,如何将源附加到Gradle Eclipse项目中的jar中?

java - 如何获取ArrayList中记录的信息?

ieee-754 - IEEE 754,除以零

c - C中的任何数字除以0,它是否属于段错误?

java - 除以 0 的正则表达式

c++ - 为什么这个被零除错误只发生在优化代码中?