Ну, после работы с этим какое-то время коллега нашел какое-то решение.Изменений в перечислении очень мало, а также необходимо внести некоторые изменения, когда вызывается valueOfAnyKey()
.Так что теперь мы можем вернуть DeviceKey, который, как мы знаем, является Enum.
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() {
...
}
}
После всего этого мы все еще не можем понять, какой тип Enum мы получаем, и для использования setting
(типа T) нам нужно привести его с помощью SmartSetting.class.cast(setting)
.Мы обсудили, дает ли это нам лучшее решение, чем предложенное Рэй Тайком, которое также было нашей первой реализацией, и пришли к выводу, что мы предоставляем немного больше подробностей о том, что возвращается, но с точки зрения вызывающих сторонВы всегда должны будете выполнять приведение класса.