我有以下界面
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;
}
}
答案 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建议的更好的解决方案,这也是我们的第一个实现,结论是我们提供了更多关于返回内容的细节,但从调用者的角度来看你将永远不得不进行课堂演出。