3

So I have several Enums defined like the following. I have a method that uses the Enum to find the value.

public enum MyEnum1
{
   STRING1("My String1"),
   STRING2("My String2"),
   STRING3("My String3"),
   STRINGLESS("String not found");

   private String s;

   private MyEnum1(String s) { this.s = s; }

   public String getValue() { return s; }
}

public enum MyEnum2
{
   STRING1("My String1"),
   STRING2("My String2"),
   STRING3("My String3"),
   STRINGLESS("String not found");

   private String s;

   private MyEnum2(String s) { this.s = s; }

   public String getValue() { return s; }
}

public class MyClass1
{
    public static String getPlacement(String myString)
    {
        for (MyEnum1 a: MyEnum1.values())
            if (myString.contains(a.toString()))
                return a.getValue();

        return MyEnum1.STRINGLESS.getValue();
     }
}

public class MyClass2
{
    public static String getPlacement(String myString)
    {
        for (MyEnum2 a: MyEnum2.values())
            if (myString.contains(a.toString()))
                return a.getValue();

        return MyEnum2.STRINGLESS.getValue();
     }
}

Right now I have 5 Enums defined that all get processed by the same getPlacement method but I had to create 5 different MyClass classes (MyClass2, MyClass3...) with MyEnum2, MyEnum3... hard coded in the For Loop to make it happen.

I've tried...

public static String getPlacement(Enum e, String myString) {}

and

public static String getPlacement(Enum<?> e, String myString) {}

but neither works.

I would like to pass an Enum to the getPlacement method as a parameter thus allowing me to only have one MyClass class that could process the 5 different Enums. Is this possible?

2 Answers 2

6

To preserve the exact semantics of your getPlacement, you can do it like this:

interface StringValue {
    String getValue();
}

enum MyEnum1 implements StringValue {
    ...
    private String stringValue;
    ...

    @Override
    public String getValue() {
        return stringValue;
    }
}

static <E extends Enum<E> & StringValue>
String getPlacement(Class<E> enumClass, String inValue) {
    for(E constant : enumClass.getEnumConstants()) {
        if(inValue.contains(constant.toString()))
            return constant.getValue();
    }
    return Enum.valueOf(enumClass, "STRINGLESS").getValue();
}

I am not sure if the exact semantics here are actually important to you. If they're not, there are simpler ways. If you don't need contains you can just use Enum#valueOf. If you can override toString (because you can also use Enum#name) then you don't need an interface.

And also, like all complicated situations with enum, things may be much simpler for you if you just do not use enum. A final class with a private constructor and public static final constants can do many things that enum can not (like inherit from an abstract supertype...).

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the help this doesn't exactly what I wanted! I'm looking for Key,Value pairs and I need have control of the order in which the keys are checked which is why I chose Enum. I'm placing users in an LDAP tree and you can be any combination of a Board member, Faculty, Staff, Consultant, Alumni, ...., and/or a Student. I need to determine your container(which controls your rights) by the hierarchy of your user type in the order I just listed. If you are a Board member and student you should be placed in the Board container. Faculty and Staff = Staff and so on. Thanks again!!!
That should say it DOES exactly what I wanted! Much thanks!!
1

Add such interface to your code.

public interface Named {
    String name();
}

Let all of your enums implement it like

public enum MyEnum1 implements Named {...}

Then declare your method with interface like:

public static String getPlacement(Named enumValue, String myString) {}

Inside of the getPlacement() method call enumValue.name() instead of toString(), although you can do the exact same with toString(), depends what you gonna use in your interface definition (which can be named as you like, not necessarily Named).

By the way, using single letters as variable names is usually considered a bad practice.

1 Comment

This worked with the exception that I could not loop through the Enum values using valueOf(). It's as if it didn't inherit the Iteration abilities of the Enum. Oh and I only use single letter variables as iterators and counters. I just got lazy and instead of creating MyVar1 or something I just used s. :-D

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.