a.solak
a.solak

Reputation: 79

What is the best way to handle java.lang.IllegalArgumentException: No enum constant

The enum class is like this:

public enum UserRoles {
    ADMIN, TEST
}

and I want to handle it, so that if there is no value in enum, it should not throw exception. I handle like this:

for(String roleString : roleStrings){
    if(roleString.isEmpty())
        continue;
    UserRoles userRole;
    try {
        userRole = UserRoles.valueOf(roleString);
    } catch(IllegalArgumentException e) {
        continue;
    }
    accountRoles.add(userRole);
}

Is there a better way to do it?

Upvotes: 2

Views: 5971

Answers (3)

Nicholas K
Nicholas K

Reputation: 15423

You can introduce a static method that will fetch the Enum values for you if found, else return null.

enum UserRoles {
    ADMIN, TEST;

    public static UserRoles fetchValue(String constant) {
       return Arrays.stream(UserRoles.values())
                    .filter(e -> e.name().equals(constant))
                    .findFirst()
                    .orElse(null);
    }
}

Now even if the Enum constant is not found null will be returned instead of an exception being thrown. Use it as follows :

UserRoles userRole = UserRoles.fetchValue(str);
if (userRole != null) {
    accountRoles.add(userRole);
}

Upvotes: 4

azro
azro

Reputation: 54168

You could handle it in a shorter way with Streams :

  • save a Map with the String as key, and the constant as value
  • look-up for the value or don't keep that one
  • collect all the ones you find
enum UserRoles {
    ADMIN, TEST;

    static Map<String, UserRoles> map = Arrays.stream(values())
                                              .collect(toMap(Enum::toString, Function.identity()));

    static List<UserRoles> parseAll(List<String> roleStrings) {
        return roleStrings.stream()                      // Stream<String>
                          .map(String::toUpperCase)      // Stream<String>
                          .map(map::get)                 // Stream<UserRoles>
                          .filter(Objects::nonNull)      // Stream<UserRoles>
                          .collect(Collectors.toList()); // List<UserRoles>
    }
}

And use as

public static void main(String[] args) {
    List<String> roleStrings = Arrays.asList("", "ADMIN", "te", "test");
    List<UserRoles> accountRoles = UserRoles.parseAll(roleStrings);
    System.out.println(accountRoles); //[ADMIN, TEST]
}

Upvotes: 1

Coderino Javarino
Coderino Javarino

Reputation: 2881

One way you could do this, is by explicitly creating a static HashMap inside your enum. Could be useful, if you expect to have a lot of unmatched values, since exceptions in general is a (relatively) costly operation. Otherwise, your way of doing is fine.

import java.util.HashMap;
public class Test {

    public static enum UserRoles {
        ADMIN, USER;

        private static HashMap<String, UserRoles> roles;
        static {
            roles = new HashMap<>();
            for (UserRoles r : UserRoles.values()) {
                roles.put(r.toString(), r);
            }
        }

        public static UserRoles parse(String s) {
            return roles.get(s);
        }
    }

    public static void main(String... args) {
        System.out.println(UserRoles.parse("ADMIN"));
        System.out.println(UserRoles.parse("FOO"));
    }

}

Upvotes: 2

Related Questions