Java Generic Enum作为参数

时间:2014-11-17 18:31:50

标签: java generics enums

所以我有几个Enums定义如下。我有一个方法,使用Enum来查找值。

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();
     }
}

现在我定义了5个Enums,它们都被同一个getPlacement方法处理,但是我必须用MyEnum2创建5个不同的MyClass类(MyClass2,MyClass3 ...),MyEnum3 ...在For循环中硬编码让它成真。

我试过......

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

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

但不起作用。

我想将一个Enum作为参数传递给getPlacement方法,因此我只能拥有一个可以处理5个不同枚举的MyClass类。这可能吗?

3 个答案:

答案 0 :(得分:1)

将此类界面添加到您的代码中。

public interface Named {
    String name();
}

让你的所有枚举都像

一样实现它
public enum MyEnum1 implements Named {...}

然后使用如下界面声明您的方法:

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

getPlacement()方法调用enumValue.name()而不是toString()内部,虽然你可以使用toString()完全相同,但取决于你在接口定义中使用的内容(可以按你的意愿命名,不一定是Named)。

顺便说一句,使用单个字母作为变量名通常被认为是一种不好的做法。

答案 1 :(得分:1)

要保留getPlacement的确切语义,您可以这样做:

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();
}

我不确定这里的确切语义对你来说是否真的很重要。如果他们不是,那就有更简单的方法。如果您不需要contains,则可以使用Enum#valueOf。如果您可以覆盖toString(因为您也可以使用Enum#name),那么您不需要界面。

而且,就像所有复杂的枚举情况一样,如果你不使用枚举,事情可能会简单得多。具有私有构造函数和final常量的public static final类可以执行枚举不能执行的许多操作(例如从抽象超类型继承...)。

答案 2 :(得分:0)

Enum基类java.lang.Enum具有静态工厂方法valueOf(Class, String),用于构造任意枚举实例。通过一些仿制魔术你应该能够解决你的问题。

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

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

   @Override
   public String toString() { return s; }
}

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

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

   @Override
   public String toString() { return s; }
}

public static void main(String[] args) {
    System.out.println(getPlacement(MyEnum1.class, "STRING1").name());
    System.out.println(getPlacement(MyEnum2.class, "STRING3").name());
    System.out.println(getPlacement(MyEnum2.class, "foobar").name());
}

public static <T extends Enum<T>> Enum<T> getPlacement(Class<T> clazz, String value) {
    try {
        return Enum.valueOf(clazz, value);
    } catch (IllegalArgumentException e) {
        return Enum.valueOf(clazz, "STRINGLESS");
    }
 }