0

Eclipse showing error Constant expression required, but all filed are final. then why throws this error. Could someone explain me where is my mistake.

package com.oca.test.exam;

public class Test {

    public static final Integer x1 = 5;
    public static final Integer x2 = 10;
    public static final Integer x3 = 15;
    public static final Integer x4 = 20;

    public static void main(String[] args) {
        switch (x1) {
        case x1: 
            System.out.println();
            break;

        case x2: 
            System.out.println();
            break;

        case x3: 
            System.out.println();
            break;

        case x4: 
            System.out.println();
            break;
        }
    }
}
Joe C
  • 15,324
  • 8
  • 38
  • 50
Ng Sharma
  • 2,072
  • 8
  • 27
  • 49
  • 7
    "*Please don't mark duplicate question Problem is new.*" - [Nope.](https://stackoverflow.com/questions/3827393/java-switch-statement-constant-expression-required-but-it-is-constant) – Turing85 Feb 24 '19 at 07:06
  • 2
    As an aside: when would `x1` not be equal to `x1`? – Turing85 Feb 24 '19 at 07:07
  • 2
    Possible duplicate of [Java switch statement: Constant expression required, but it IS constant](https://stackoverflow.com/questions/3827393/java-switch-statement-constant-expression-required-but-it-is-constant) – Joe C Feb 24 '19 at 07:13
  • use case 5: System.out.println(); break; case 10: System.out.println(); break; case 15: System.out.println(); break; case 20: System.out.println(); break; default: System.out.println(); break; – javaworld Feb 24 '19 at 07:13

3 Answers3

1

A TL;DR is at the end.

Looking into the documentation of the switch statement we can find the following:

A switch works with the byte, short, char, and int primitive data types. It also works with enumerated types (discussed in Enum Types), the String class, and a few special classes that wrap certain primitive types: Character, Byte, Short, and Integer (discussed in Numbers and Strings).

At first this seems fine and your problem shouldn't exist. However the definition does not mention where those wrappers can be used and where not. Looking into the specs of the switch-statements (JLS) we find that a switch has the form of:

1 Switch-Expression

SwitchStatement: switch ( Expression ) SwitchBlock

The Expression is further explained:

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.

So here, it's totally fine to use a wrapper class such as Integer. The compiler will manage.

2 Switch-Block

The switch-block can be broken down into:

SwitchLabels BlockStatements

The SwitchLabel is defined as:

SwitchLabel: case ConstantExpression : case EnumConstantName : default :

So a label will only accept constant expressions or enums. If we now have a look at the definition of a constant expressions, we'll find:

A constant expression is an expression denoting a value of primitive type or a String...

Of course some conditions have to apply to make primitive type a constant (it is listed there) but in your case the important part is that you have to use a primitive type or a String.

BONUS

The exchange between wrapper class and primitive type is called "autoboxing or unboxing" (depending on the direction). According to the documentation, unboxing takes place when:

Converting an object of a wrapper type (Integer) to its corresponding primitive (int) value is called unboxing. The Java compiler applies unboxing when an object of a wrapper class is:

  • Passed as a parameter to a method that expects a value of the corresponding primitive type.
  • Assigned to a variable of the corresponding primitive type.

So it seems like Java is simply not built to to make the required unboxing in order for the switch-statement to work, as you intended.

----------------------

TL;DR

For the switch expression you can use the wrapper class. For the labels however you can only use the primitive types: byte, short, char and int.

Younes El Ouarti
  • 2,200
  • 2
  • 20
  • 31
0

case expressions must be constant expressions , you can use enum it's better for constant values and more readable code , here is example for enum :

enum class :

    public enum Numbers {

    HIGH(3), // calls constructor with value 3
    MEDIUM(2), // calls constructor with value 2
    LOW(1) // calls constructor with value 1
    ; // semicolon needed when fields / methods fol
    private final int levelCode;

    Numbers(int levelCode) {
        this.levelCode = levelCode;
    }

    public int getLevelCode() {
        return this.levelCode;
    }
}

for you main method :

public class Test {

    public static void main(String[] args) {
        switch (Numbers.HIGH) {
        case HIGH:
            System.out.println("hight");
            break;

        case MEDIUM:
            System.out.println("medium");
            break;

        case LOW:
            System.out.println("low");
            break;

        }

    }
}
yali
  • 1,038
  • 4
  • 15
  • 31
  • you use `Numbers.HIGH` in the `switch` condition, but `HIGH`, `MEDIUM` and `LOW` in the cases. This could lead to nasty bugs. – Turing85 Feb 24 '19 at 07:44
  • i know , but that's for him to understand what the better for hime, he want to use x1 in switch statement, so he already want use final for constant value , but switch is better than final values – yali Feb 24 '19 at 07:49
-1

Variables declared as final in Java are not considered compile time constants, because their values can still change at runtime - from an undefined state to a defined one.

Case values must be defined on the spot, eg. case 5: case 12: case "green":

SoyChai
  • 320
  • 2
  • 11