返回特定接口枚举的枚举方法

时间:2011-11-08 10:42:58

标签: java generics interface enums enumeration

我有以下界面

public interface DeviceKey {
    String getKey();
}

我也有各种枚举,都扩展了这个界面。

在包含所有枚举的类中,我想要一个基于字符串(键)的方法,可以返回与该字符串对应的枚举。该字符串与枚举相关,但它不是名称。我的班级和enum看起来像这样:

public class Settings {
    private static final Map<String, DeviceKey> lookupAll = Maps.newHashMap();
    static {
        lookupAll.putAll(SmartSetting.lookup);
        // Plus a lot more similar to these
    }

    public static DeviceKey valueOfAnyKey(String key) {
        return lookupAll.get(key);
    }

    public enum SmartSetting implements DeviceKey {
        STATUS("smart_status");

        private static final Map<String, SmartSetting> lookup = EnumUtil.addAll(SmartSetting.class);
        private final String key;

        SmartEncryptionSetting(String key) {
            this.key = key;
        }

        @Override
        public String getKey() {
            return key;
        }
    }
}

valueOfAnyKey()的当前实现返回DeviceKey,当然这不是枚举。为了使valueOfAnyKey()返回DeviceKey类型的枚举,我该怎么办?

EnumUtil:

private static class EnumUtil {

    public static <T extends Enum<T> & DeviceKey> Map<String, T> addAll(Class<T> theClass) {
        final Map<String, T> retval = new HashMap<String, T>();
        for(T s : EnumSet.allOf(theClass)) {
            retval.put(s.getKey(), s);
        }
        return retval;
    }
}

3 个答案:

答案 0 :(得分:0)

可能是这样的:

import java.util.*;
interface Key {
    String get();
}
class Enums {
    enum Color implements Key {
        r("foo"), g("bar"), b("baz");
        Color(String key) {
            this.key = key;
        }
        public String get() {
            return key;
        }
        final String key;
    }
    enum Day implements Key {
        m("quux"), t("fred"), w("hozer");
        Day(String key) {
            this.key = key;
        }
        public String get() {
            return key;
        }
        final String key;
    }
    static final Map<String, Enum> map = new LinkedHashMap<String, Enum>();
    static {
        for (Color c : Color.values())
            map.put(c.get(), c);
        for (Day d : Day.values())
            map.put(d.get(), d);
    }
}
public class Main {
    public static void main(String[] args) {
        for (Enums.Color c : Enums.Color.values())
            System.out.println(c+" "+c.get()+" "+Enums.map.get(c.get()));
        for (Enums.Day d : Enums.Day.values())
            System.out.println(d+" "+d.get()+" "+Enums.map.get(d.get()));
    }
}

答案 1 :(得分:0)

在Java中,方法只能返回一种类型。您不能让它返回DeviceKey“和”Enum

答案 2 :(得分:0)

好吧,经过一段时间的努力,一位同事找到了解决方案。枚举的变化非常少,并且在调用valueOfAnyKey()时也需要进行一些更改。 所以现在我们能够返回一个我们知道是Enum的DeviceKey。

public class Settings {
    private static final Map<String, Enum<?>> lookupAll = Maps.newHashMap();
    static {
        lookupAll.putAll(SmartSetting.lookup);
        // Plus a lot more similar to these
    }

    public static <T extends Enum<T> & DeviceKey> T valueOfAnyKey(String name) {
        return (T) lookupAll.get(name);
    }

    public enum SmartSetting implements DeviceKey {
        STATUS("smart_status");

        private static final Map<String, SmartSetting> lookup = EnumUtil.addAll(SmartSetting.class);
        private final String key;

        SmartEncryptionSetting(String key) {
            this.key = key;
        }

        @Override
        public String getKey() {
            return key;
        }
    }
}

现在按照以下方式查找设置。 IntelliJ和eclipse都没有任何问题遗漏<T>,但Oracle编译器坚持认为它存在。

T setting = DeviceSetting.<T>valueOfAnyKey("settingName);

现在应该在方法或类级别定义<T>。如果它是在方法级别定义的,那么有时您也会遇到Oracle编译器的问题,因此建议将定义添加到类中。

或者:

public class SomeClass <T extends Enum<T> & DeviceKey> {
    ....
}

public class SomeClass {
    public <T extends Enum<T> & DeviceKey> void aMethod() {
        ...
    }
}

毕竟,它仍然让我们不知道我们要回到什么样的枚举,并且为了使用setting(类型为T),我们需要使用SmartSetting.class.cast(setting)来强制转换它。 我们已经讨论过这是否真的给了我们比Ray Tayek建议的更好的解决方案,这也是我们的第一个实现,结论是我们提供了更多关于返回内容的细节,但从调用者的角度来看你将永远不得不进行课堂演出。