繁体   English   中英

Java通用枚举作为参数

[英]Java Generic Enum as a Parameter

所以我有几个定义如下的枚举。 我有一个使用枚举查找值的方法。

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个枚举,所有的枚举都由相同的getPlacement方法处理,但是我必须使用ForE循环中的MyEnum2,MyEnum3 ...创建5个不同的MyClass类(MyClass2,MyClass3 ...),以使其实现。

我试过了...

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

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

但都行不通。

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

将这样的界面添加到您的代码中。

public interface Named {
    String name();
}

让您所有的枚举都像

public enum MyEnum1 implements Named {...}

然后使用如下接口声明您的方法:

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

getPlacement()方法内部,调用enumValue.name()而不是toString() ,尽管您可以使用toString()进行完全相同的操作,但这取决于您在接口定义中使用的名称(可以按您的喜好命名,而不是必须Named )。

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

要保留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 ),则不需要接口。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM