33

As far as I understand the Java 8 JLS the expression (1/0) is considered a constant expression, but when I try to compile the following program with OpenJDK 8 I get an error

public class Switch {
    public static void main(String[] args) {
        switch(42) {
            case (1/0):
                return;
            default:
                return;
        }
    }
}

The error says (1/0) isn't a constant expression

Switch.java:4: error: constant expression required
            case (1/0):
                 ^
1 error

Am I missing something? Or is it a bug in OpenJDK 8?

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
ReyCharles
  • 1,772
  • 10
  • 30

2 Answers2

35

The compiler is doing constant folding (precomputing trivial literal expressions). This is a case where the expression "completes abruptly", to use the JLS verbiage, disqualifying it from meeting the definition of "constant expression". So it's not a bug, it's consistent with the JLS.

And yes, the expression doesn't evaluate to a value either (warning the user trying to do something like this that the result will not be a constant expression), but the compiler doesn't know that until it tries. Not evaluating to a value and completing abruptly would seem to go hand-in-hand.

Adding a variable declaration like

int x = 1 / 0;

doesn't cause a compiler error, it's the switch that forces the expression to be evaluated at compile time.

By the way I checked that this happens for version 7 of the Oracle and IBM JDKs too, it's not OpenJDK or JDK8 specific.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
15

A constant expression must be able to evaluate to a value, since the compiler must reconduce that expression to a value.

1/0 doesn't have any value.

From JSL §15.28:

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:

Jack
  • 131,802
  • 30
  • 241
  • 343
  • 6
    I think the emphasis should be on `that does not complete abruptly` i.e. throw an `java.lang.ArithmeticException`! Good catch, thanks! – ReyCharles Jul 03 '15 at 12:28
  • It depends, since the point is that it completes abruptly if it doesn't have an evaluable value, which is the case in this situation. The "denoting a value" is more mathematical related constraint while completing abruptly is more a pragmatic constraint. Actually the exception is not even thrown since constant folding is done while compiling not during execution, it's a real special case. – Jack Jul 03 '15 at 12:32
  • 1
    Conversely you could say it doesn't have a value because it completes abruptly. The JLS is pretty clear on when an expression completes abruptly (e.g. integer division by zero), whereas it's not so nice to use what expressions denote when defining what expressions are / denote. https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.6 – ReyCharles Jul 03 '15 at 12:44
  • No, it doesn't have a value regardless Java so the fact that evaluation completes abruptly is irrelevant to give that expression a value, https://en.wikipedia.org/wiki/Undefined_(mathematics) – Jack Jul 03 '15 at 12:57
  • 3
    1.0 / 0.0 has a value in Java regardless of mathematics. – ReyCharles Jul 03 '15 at 13:04
  • 1.0/0.0 has a value just because mathematics assigned one to it, which is rather the opposite of what you are saying. And you can't use a float because of §14.11: _The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, String, or an enum type (§8.9), or a compile-time error occurs_. Otherwise it would be perfectly legal, `if (1.0f/0.0f == value)` is legal indeed. – Jack Jul 03 '15 at 13:18