ChatGPT解决这个技术问题 Extra ChatGPT

Java: using switch statement with enum under subclass

First I'll state that I'm much more familiar with enums in C# and it seems like enums in java is a quite mess.

As you can see, I'm trying to use a switch statement @ enums in my next example but I always get an error no matter what I'm doing.

The error I receive is:

The qualified case label SomeClass.AnotherClass.MyEnum.VALUE_A must be replaced with the unqualified enum constant VALUE_A

The thing is I quite understand the error but I can't just write the VALUE_A since the enum is located in another sub-class. Is there a way to solve this problem? And why is it happening in Java?

//Main Class
public class SomeClass {

    //Sub-Class
    public static class AnotherClass {
        public enum MyEnum {
            VALUE_A, VALUE_B
        }    
        public MyEnum myEnum;
    }

    public void someMethod() { 
        MyEnum enumExample //...

        switch (enumExample) {
            case AnotherClass.MyEnum.VALUE_A: { <-- error on this line
                //..
                break;
            }
        }
    }
}
As darrengorman commented, Java Enum are extremely handy once you get the hang of them – not at all a mess. They are much more flexible and practical than simple enums (merely a labeled integer value) as seen on other platforms. See the Oracle Tutorial. Discover the optimized Set/Map implementations: EnumSet & EnumMap.
When you try to qualify the case statement; in a way, you are trying to say that I can mix different types of enums (not just same enum type) within a single switch statement. Java has stopped it with this approach as discussed here digizol.com/2010/10/enum-case-label-switch-java-qualified.html
This happened to me while refactoring (moving) a class in IntelliJ 2018.2

d
darrengorman

Change it to this:

switch (enumExample) {
    case VALUE_A: {
        //..
        break;
    }
}

The clue is in the error. You don't need to qualify case labels with the enum type, just its value.


Ok i feel so stupid :-( You are totally right, i was convinced i tried this exact line and got an error with that so i moved to qualify case, but your suggestion DOES work.
By the way I think you'll find that enums in Java are incredibly useful once you start to use them more, I wouldn't say they're a mess at all :)
@milkplusvellocet, I know this post is already old, but I'm curious why Java don't allow the qualified case label in the switch statement?
@cRane01 don't know for sure, but it makes for a cleaner syntax. Specifying the type on each case would be totally redundant
@HelloGoodbye No. The switch statement's variable defines the type of the case statement so it can only be one enum.
P
Pika Supports Ukraine

Wrong:

case AnotherClass.MyEnum.VALUE_A

Right:

case VALUE_A:

I upvoted yours because it is clearer on what the issue is.
K
Kru

Java infers automatically the type of the elements in case, so the labels must be unqualified.

int i;
switch(i) {
   case 5: // <- integer is expected
}
MyEnum e;
switch (e) {
   case VALUE_A: // <- an element of the enumeration is expected
}

Why must it be unqualified?
If you could qualify, then you might use something else than MyEnum which would not make sense.
@Kru, but I can use something grammatically-else for non-enum-typed case expressions. E.g. static final int MY_CONST = 7; …; switch(intVariable) {case MY_CONST: …;} instead of case 7. So this restriction for enums makes no sense (I can use not only primary literals, but also manually-defined constants for integer switch expression, but I can't use manually-defined constants, but only primary names for enums).
@Sasha enums in Java don't have integers assigned to them like in C++. They are abstract just like java boolean.
@user13947194, nobody said they have. I just pointed out the logical fallacy: for one type we can use both the primary literals and the manually-defined constants while for the other type we can use only primary names but not manually-defined constants.
W
Woyzeck

this should do:

//Main Class
public class SomeClass {

    //Sub-Class
    public static class AnotherClass {
        public enum MyEnum {
            VALUE_A, VALUE_B
        }    
        public MyEnum myEnum;
    }

    public void someMethod() { 
        AnotherClass.MyEnum enumExample = AnotherClass.MyEnum.VALUE_A; //...

        switch (enumExample) {
            case VALUE_A: { //<-- error on this line
            //..
            break;
            }
        }
    }
}

You saved the day!
h
hbamithkumara

From Java 14 onwards, one can use switch expressions.

For this post

public enum MyEnum {
    VALUE_A, VALUE_B;
}
public void someMethod() { 
    MyEnum enumExample //...

    switch (enumExample) {
        case VALUE_A -> {
            // logic
        }
        case VALUE_B -> {
            // logic
        }   
    }
}

Switch expression

Like all expressions, switch expressions evaluate to a single value and can be used in statements. They may contain "case L ->" labels that eliminate the need for break statements to prevent fall through. You can use a yield statement to specify the value of a switch expression.

public enum Month {
    JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC;
}

Example 1: Returns value.

public static int getNoOfDaysInAMonth(Month month, boolean isLeapYear) {
    return switch(month) {
        case APR, JUN, SEP, NOV -> 30;
        case FEB -> (isLeapYear)? 29: 28;
        case JAN, MAR, MAY, JUL, AUG, OCT, DEC -> 31;
    };
}

Example 2: Doesn't returns value.

public static void printNoOfDaysInAMonth(Month month, boolean isLeapYear) {
    switch(month) {
        case APR, JUN, SEP, NOV -> {
            System.out.println("30 days");
        }
        case FEB -> {
            System.out.println(((isLeapYear)? 29: 28) + " days");
        }
        case JAN, MAR, MAY, JUL, AUG, OCT, DEC -> {
            System.out.println("31 days");
        }
    };
}

Reference

Switch Expressions


J
Jimit Patel

This is how I am using it. And it is working fantastically -

public enum Button {
        REPORT_ISSUES(0),
        CANCEL_ORDER(1),
        RETURN_ORDER(2);

        private int value;

        Button(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }
    }

And the switch-case as shown below

@Override
public void onClick(MyOrderDetailDelgate.Button button, int position) {
    switch (button) {
        case REPORT_ISSUES: {
            break;
        }
        case CANCEL_ORDER: {
            break;
        }
        case RETURN_ORDER: {
            break;
        }
    }
}

d
dash1e

Write someMethod() in this way:

public void someMethod() {

    SomeClass.AnotherClass.MyEnum enumExample = SomeClass.AnotherClass.MyEnum.VALUE_A;

    switch (enumExample) {
    case VALUE_A:
        break;
    }

}

In switch statement you must use the constant name only.