So, I am working on this class that has a few static constants:
public abstract class Foo {
...
public static final int BAR;
public static final int BAZ;
public static final int BAM;
...
}
Then, I would like a way to get a relevant string based on the constant:
public static String lookup(int constant) {
switch (constant) {
case Foo.BAR: return "bar";
case Foo.BAZ: return "baz";
case Foo.BAM: return "bam";
default: return "unknown";
}
}
However, when I compile, I get a constant expression required error on each of the 3 case labels.
I understand that the compiler needs the expression to be known at compile time to compile a switch, but why isn’t Foo.BA_ constant?
While they are constant from the perspective of any code that executes after the fields have been initialized, they are not a compile time constant in the sense required by the JLS; see §15.28 Constant Expressions for the specification of a constant expression1. This refers to §4.12.4 Final Variables which defines a “constant variable” as follows:
In your example, the Foo.BA* variables do not have initializers, and hence do not qualify as “constant variables”. The fix is simple; change the Foo.BA* variable declarations to have initializers that are compile-time constant expressions.
In other examples (where the initializers are already compile-time constant expressions), declaring the variable as
finalmay be what is needed.You could change your code to use an
enumrather thanintconstants, but that brings another couple of different restrictions:defaultcase, even if you havecasefor every known value of theenum; see Why is default required for a switch on an enum?caselabels must all be explicitenumvalues, not expressions that evaluate toenumvalues.1 – The constant expression restrictions can be summarized as follows. Constant expressions a) can use primitive types and
Stringonly, b) allow primaries that are literals (apart fromnull) and constant variables only, c) allow constant expressions possibly parenthesised as subexpressions, d) allow operators except for assignment operators,++,--orinstanceof, and e) allow type casts to primitive types orStringonly.Note that this doesn’t include any form of method or lambda calls,
new,.class..lengthor array subscripting. Furthermore, any use of array values,enumvalues, values of primitive wrapper types, boxing and unboxing are all excluded because of a).