12

Possible Duplicate:
Is 1/0 a legal Java expression?

Why does this code compile?

class Compiles {
    public final static int A = 7/0;
    public final static int B = 10*3;

    public static void main(String[] args) {}
}

If I take a look in the compiled class file, I can see that B has been evaluated to 30, and that A still is 7/0.

As far as I understand the JSL an expression where you divide by zero is not a constant.

Ref: JLS 15.28

My above statement is due to this line:

A compile-time constant expression is an expression denoting a value of primitive type

Hence dividing by zero is not evaluated to a primitive value.

What I really dont understand is why the compiler allows this anyway? Just to be clear, my code above crashes runtime with a "java.lang.ExceptionInInitializerError"

As it seems to me the compiler threats any final static variable as a constant and evaluates it compile time. That means that the compiler already has tried to evaluate A, but since it was a division by zero it just let it go through. No compile time error. But this seems very very bizarre... The compiler knows it is a divide by zero and that it will crash runtime but nevertheless it doesn't flag a compile error!

Can anyone explain to me why?

Community
  • 1
  • 1
laitinen
  • 153
  • 1
  • 7
  • 1
    Is there any instance of division by zero producing compile-time errors at all? If you divided by zero in normal procedural code you would get an `ArithmeticException` in runtime, so I see nothing surprising about this getting through the compiler too. – BoltClock Feb 12 '11 at 20:20

2 Answers2

7

To throw an java.lang.ExceptionInInitializerError is the only correct behavior.

If your code did not compile, a perfectly valid Java program would have been rejected, and that would have been a bug.

The only correct alternative to putting 7/0 in the compiled code, would actually be to explicitly throw a ExceptionInInitializerError, but how much more useful is that?

The compiler knows it is a divide by zero and that it will crash runtime but nevertheless it does flag a compile error!

Actually, I wouldn't agree with that... would this program crash?

class Compiles {
    public final static int A = 7/0;
    public final static int B = 10*3;

    public static void main(String[] args) {}

}

public class Test {

    // Application entry point.
    public static void main(String[] args) {
        try {
            new Compiles();

            launchTheMissiles();

        } catch (ExceptionInInitializerError e) {

            doUsefulStuff();

        }
    }
}
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • Your program will not crash. But mine will. So you will always put initialization of new objects in a try/catch?? – laitinen Feb 12 '11 at 20:32
  • 1
    Yes. I always put try/catch around instantiations of `ExceptionInitializerError`-classes. ;-D – aioobe Feb 12 '11 at 20:35
  • By that logic there should be no compile time errors at all, for you could enclose any statement with a try-catch. Is that a fair assessment? – Allohvk May 24 '21 at 06:34
  • 1
    @Allohvk, unclear to me how that would work. What exception would something like `aoeu]aoeu(ueao` throw? The Eclipse compiler can [compile it to throw an Error](https://stackoverflow.com/questions/1124788/java-unresolved-compilation-problem) but it is still not a valid Java program. It would be very hard and complicated to formalize error recovery. When does the actual error end, and where does the catch clause start? For example, should this be an acceptable Java program: `try{ao]/*%+^/eu}catch}}catch(Error e){}` – aioobe May 24 '21 at 07:28
  • I see your point. But I believe that's what the OP is trying to tell. If we know for sure there is going to be an error, we should throw a compile error right? The "divide by zero" is actually just as crazy to let pass by as the "aoeu]aoeu(ueao". Maybe there are backward compatibility or other issues due to which this cannot be done..But was a bit surprised to see an obvious divide/0 error would have to wait till runtime – Allohvk May 24 '21 at 10:20
  • 1
    Ok, yeah, you're right. So, you could rephrase your previous comment as "By that logic, there should be no compile time errors for _syntactically valid_ programs." (which is obviously not desirable.) So I agree, there is a middle ground here, and nothing would have prevented the creators of disallowing `7/0`. – aioobe May 24 '21 at 11:25
2

JLS 15.28 Constant Expression:

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:

...

Therefore 7/0 is not a compile-time constant, since its evaluation completes abruptly due to division by zero. So, it's treated as a regular run-time expression, and throws an exception in runtime.

Community
  • 1
  • 1
axtavt
  • 239,438
  • 41
  • 511
  • 482
  • That was what I said! I totally agree. But I find it weird that it doesnt flag it as a compile error, since the compiler already has evaluated the expression? – laitinen Feb 12 '11 at 20:29
  • 3
    If you agree that it is not a *compile-time* constant, then you shouldn't be surprised that the evaluation is deferred to *runtime*, and consequently throw an exception. – aioobe Feb 12 '11 at 20:30
  • 4
    that's probably a patch to justify existing javac behavior (can't change it due to backward compatibility). the spec could have very well said: "blah blah, **and it is a compile time error if the expression doesn't compute**" – irreputable Feb 13 '11 at 01:06