5
\$\begingroup\$

I have this enum below:

public enum TestEnum {
 h1, h2, h3, h4;
 public static String forCode(int code) {
 return (code >= 0 && code < values().length) ? values()[code].name() : null;
 }
 public static void main(String[] args) {
 System.out.println(TestEnum.h1.name());
 String ss = "h3";
 try {
 TestEnum.valueOf(ss); // but this validates with all the enum values
 System.out.println("valid");
 } catch (IllegalArgumentException e) {
 System.out.println("invalid");
 } 
 }
}

I need to check if the enum value represented by my string ss is one of my enum values h1, h2 or h4. So if h3 is being passed as a string, I would like to return false or throw IllegalArgumentException. I won't need to validate ss with h3 in the enum.

I came up with the below code to do this with the enum, but I believe there is a more elegant solution.

public enum TestEnum {
 h1, h2, h3, h4;
 public static boolean checkExcept(String el, TestEnum... except){
 boolean results = false;
 try{
 results = !Arrays.asList(except).contains(TestEnum.valueOf(el));
 }catch (Exception e){}
 return results;
 }
 public static String forCode(int code) {
 return (code >= 0 && code < values().length) ? values()[code].name() : null;
 }
 public static void main(String[] args) {
 String ss = "h3";
 if(TestEnum.checkExcept(ss,TestEnum.h1, TestEnum.h2, TestEnum.h3)){
 System.out.println("valid");
 }else{
 System.out.println("invalid");
 }
 }
}

Is there any better way of solving this problem?

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Feb 23, 2014 at 20:05
\$\endgroup\$

3 Answers 3

6
\$\begingroup\$

I would pass a TestEnum instead of a String to your method, forcing the exception handling to be outside the method. I don't see why you are using Strings at all actually (although I suspect that this is only a small part of your code, and that you have your reasons for needing this).

I would do some refactoring and use EnumSet, which could make your code something like this: (untested code, but I believe it should work)

public static void main(String[] args) {
 String enumName = "h3";
 EnumSet<TestEnum> except = EnumSet.of(TestEnum.h1, TestEnum.h2, TestEnum.h3);
 boolean valid;
 try {
 valid = !except.contains(TestEnum.valueOf(enumName));
 } catch (IllegalArgumentException e) { valid = false; }
 System.out.println(valid ? "valid" : "invalid");
}

Note that I have gotten rid of your entire method here as I think that when you use EnumSet like this, you don't need the method. But of course you can put the relevant parts of the above code into a method.

answered Feb 23, 2014 at 20:30
\$\endgroup\$
4
  • \$\begingroup\$ What about if the String enumName is h10? It should return false as well? Correct? But it is throwing exception with your current code. \$\endgroup\$ Commented Feb 23, 2014 at 21:00
  • \$\begingroup\$ @user2809564 As if that's a big problem to solve.... ;) See edit. \$\endgroup\$ Commented Feb 23, 2014 at 21:12
  • \$\begingroup\$ @ringbearer If you pass enumName = "h4" in this case it is a valid enum and will not throw, but contains will return false. \$\endgroup\$ Commented Apr 13, 2017 at 9:11
  • \$\begingroup\$ Right, i assumed before noting that OP wanted a filter. \$\endgroup\$ Commented Apr 13, 2017 at 10:49
2
\$\begingroup\$

You can create an isValid or checkValid method inside the enum and override it in h3 if it's not changing runtime.

public enum TestEnum {
 h1, 
 h2, 
 h3 {
 @Override
 public boolean isValid() {
 return false;
 }
 },
 h4;
 public boolean isValid() {
 return true;
 }
}

It returns true for h1, h2 and h4, false for h3.

You could eliminate the results variable from checkExcept:

public static boolean checkExcept(String el, TestEnum... except) {
 try {
 return !Arrays.asList(except).contains(TestEnum.valueOf(el));
 } catch (Exception e) {
 return false;
 }
}

Please note that catching Exception is almost always a bad idea. I'd catch a more specific exception here (IllegalArgumentException).

answered Feb 23, 2014 at 20:58
\$\endgroup\$
1
  • \$\begingroup\$ Overriding the isValid method is not a flexible solution for different validation requirements. I agree with catching IllegalArgumentException though. \$\endgroup\$ Commented Feb 23, 2014 at 21:14
2
\$\begingroup\$

Catching exception or its sub type is bad idea. This should do it more proper way as mentioned code below.

public static boolean contains(String test) {
 for (EnumType type : EnumType.values()) {
 if (type.name().equals(test)) {
 return true;
 }
 }
 return false;
}
answered Mar 9, 2015 at 11:44
\$\endgroup\$
1
  • \$\begingroup\$ This is generally a good option, but in this case it doesn't solve the same problem. The question asks for I need to check if the enum value represented by my string ss is one of my enum values h1, h2 or h4. So if h3 is being passed as a string, I would like to return false or throw IllegalArgumentException. \$\endgroup\$ Commented Mar 9, 2015 at 14:33

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.