switch over value of enum: case expressions must be constant expressions

17,048

Solution 1

This seems perfectly legal to me

Well it's not - a method call is never a constant expression. See JLS 15.28 for what constitutes a constant expression. And a case value always has to be a constant expression.

The simplest fix would be to have a Friend.fromFullName static method, which perhaps looked the Friend up in a HashMap<String, Friend>. (You don't have to have that method in Friend of course... it's just that would be the most conventional place.) Then you could switch over the enum rather than the name.

As a side note, your enum name should be in the singular and with ALL_CAPS members, so Friend.PETER etc.

Solution 2

If I understand your question, you can use valueOf(String) like

String name = "Peter";
Friends f = Friends.valueOf(name);
switch (f) {
case Peter:
    System.out.println("Peter");
    break;
case Ian:
    System.out.println("Ian");
    break;
case Sarah:
    System.out.println("Sarah");
    break;
default:
    System.out.println("None of the above");
}

Also, this

private Person(String fullName, String occupation) {
    this.fullName = fullName;
    this.occupation = occupation;
}

Should be

private Friends(String fullName, String occupation) {
    this.fullName = fullName;
    this.occupation = occupation;
}

Because Person != Friends.

Edit

Based on your comment, you will need to write a static method to get the correct Friends instance,

    public static Friends fromName(String name) {
        for (Friends f : values()) {
            if (f.getFullName().equalsIgnoreCase(name)) {
                return f;
            }
        }
        return null;
    }

Then you can call it with,

    String name = "Peter von Reus";
    Friends f = Friends.fromName(name);

valueOf(String) will match the name of the enum field. So "Ian", "Sarah" or "Peter".

Share:
17,048
Ian2thedv
Author by

Ian2thedv

My main quest in life is not dying. Side quests includes hiking, surfing and becoming a master chef. Major time wasters are sleeping, reading, gaming and failing to persuade my girlfriend wife to eat my lasagne. I also like coding. COVID update: still doing pretty good on main quest, but miserably failed the "Impress wife with cooking" side quest. I have recently embarked on the "How long can I stay inside without anyone asking questions" side quest, which has been a lot more fun than originally anticipated.

Updated on June 05, 2022

Comments

  • Ian2thedv
    Ian2thedv about 2 years

    I have an enum with the following structure:

    public enum Friends {
        Peter("Peter von Reus", "Engineer"),
        Ian("Ian de Villiers", "Developer"),
        Sarah("Sarah Roos", "Sandwich-maker");
    
        private String fullName;
        private String occupation;
    
        private Person(String fullName, String occupation) {
            this.fullName = fullName;
            this.occupation = occupation;
        }
    
        public String getFullName() {
            return this.fullName;
        }
    
        public String getOccupation() {
            return this.occupation;
        }
    }
    

    I would now like to use switch to determine, if a variable name is associated with a certain enum:

    //Get a value from some magical input
    String name = ...
    
    switch (name) {
        case Friends.Peter.getFullName():
            //Do some more magical stuff
            ...
        break;
        case Friends.Ian.getFullName():
            //Do some more magical stuff
            ...
        break;
        case Friends.Sarah.getFullName():
            //Do some more magical stuff
            ...
        break;
    }
    

    This seems perfectly legal to me, but I'm getting the error case expressions must be constant expressions in Eclipse. I can get around this with a simple set of if statements but I would like to know the reason for this error and how things might go south if this was allowed.

    NOTE: I cannot change the structure of Friends

  • Jon Skeet
    Jon Skeet almost 10 years
    No, because the name would be "Peter von Reus", not "Peter".
  • dlucci
    dlucci over 7 years
    @ElliottFrisch why can you access the enum members in the case statement without the enum name before it (PETER instead of FRIENDS.PETER)?
  • Elliott Frisch
    Elliott Frisch over 7 years
    Because the static method is in the enum.