6

I was working on switch case.

If we use class.getName(), then, I am getting error that "case expressions must be constant expressions" as follows:

switch(param.getClass().getName())
    {
        case String.class.getName():
            // to do
            break;
    }

Even if we do following, take string class name in a constant, then also, getting same error:

public static final String PARAM_NAME = String.class.getName();
switch(param.getClass().getName())
    {
        case PARAM_NAME:
            // to do
            break;
    }

But, if I do following, use the string literal "java.lang.String", there is not error:

public static final String PARAM_NAME = "java.lang.String";

Can anybody please explain this, why its not taking first two cases and taking the last one? Thanks in advance.

Krishna Kumar
  • 511
  • 1
  • 9
  • 21

3 Answers3

9

classObject.getName() is a method call, and the results of method calls are by definition not compile-time constants. A string literal is a compile-time constant.

Note that while many situations could take a static final reference as a constant for the lifetime of the program, a switch has to have its options hard-coded at compile-time. The value of a case target must be either an enum value or a (compile-time) ConstantExpression.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • But, I am taking that in 'static final'(ie, constant) variable as well, then, also its not taking it? – Krishna Kumar Nov 11 '15 at 08:17
  • the compiler does some magic and I assume the two first things are compile into the exact same byte code. The last you give, there the String literal is used and therefore it works – Emerson Cod Nov 11 '15 at 08:18
  • 2
    @KrishnaKumar A `static final` field is not necessarily a compile-time constant, even if for practical purposes it's a constant at runtime. – chrylis -cautiouslyoptimistic- Nov 11 '15 at 08:20
  • 3
    A `final` variable is a compile-time constant if, and only if, it is immediately initialized with a compile-time constant. Note that it doesn’t have to be `static` for that, it doesn’t even have to be a field, the rule applies to local variables as well. – Holger Nov 11 '15 at 08:42
6

Every case label must be a "constant expression". What is "constant expression" is defined in Java Language Standard, §15.28 Constant Expressions:

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:

  • Literals of primitive type and literals of type String

...

  • Simple names that refer to constant variables

No method calls are listed there, so method call result cannot be the constant expression even if the method is trivial. But "Simple names that refer to constant variables" are listed here, so reference to the constant variable is also a constant.

Community
  • 1
  • 1
Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
4

The reason this does not work is that the value of the case to switch on needs to be known at compile-time (because it is hard-coded and inlined in the bytecode).

String.class.getName() is a method call that gets evaluated at runtime. Yes, static final guarantees that it does not change after the class is initially loaded. But all that is long after compile-time.

The compiler never calls any code from application source code (with the possible exception of annotation processing). It only compiles it.

Thilo
  • 257,207
  • 101
  • 511
  • 656