![](/img/trans.png)
[英]How do I create a generic method to return an array of the enum values instead of its constants?
[英]How do I retrieve the interface of the constants from a generic enum type?
我为一个必须处理通用枚举的类指定一个方法的参数(我的意思是,该类可能是库的一部分,并且用户将为该类方法提供用户定义的枚举,其特定类型对于正在设计的类是未知的-我们将此类称为“库类”)。
我想在语法上尽可能地限制该参数类型,以便只允许使用正确的类型。
我的要求是,该类型必须是实现特定接口EnumKind
的枚举:
public interface EnumKind {
String getText();
}
到目前为止,我已经能够编写这种类型的代码:
Class<? extends Enum<? extends EnumKind>> t;
有了该声明,并具有以下内容:
public enum MyEnumKind implements EnumKind {
// ...
public String getText() {
// TODO Auto-generated method stub
return null;
}
}
public class MyClassKind implements EnumKind {
@Override
public String getText() {
// TODO Auto-generated method stub
return null;
}
}
public enum MyEnum {
}
只有t = MyEnumKind.class
是正确的,其他分配(例如t = MyClassKind.class
) t = MyClassKind.class
编译器拒绝,这是我想要的行为。
现在,在我的方法主体中,我可以成功执行以下操作:
Enum<? extends EnumKind>[] tt = t.getEnumConstants();
但是我还没有找到一种直接检索EnumKind
的方法来访问每个枚举常量getText()
方法。
我如何在没有显式转换的情况下获取EnumKind
元素数组? 该类型声明是我能写的最好的,还是可以改进它?
如果无法避免显式强制转换,那么我可以100%安全地声明类型声明将避免引发任何ClassCastException
(或任何类似异常)的可能性吗?
编辑
我将进一步说明,因为我遇到了另一个障碍。
EnumKind
接口要求枚举将字符串与每个枚举常量关联,即:
public enum MyEnumKind implements EnumKind {
A("#A#"),
B("#B#"),
C("#C#");
private String text;
private Token(String text) {
this.text = text;
}
@Override
public String getText() {
return text;
}
}
接下来,我想检索对应于特定字符串的枚举常量,例如
? enumValue = getValueFor("#A#");
enumValue
(它的类型应该是什么?)在这里应该表示MyEnumKind.A
,并且不需要知道实际值,因为enumValue
将传递给另一个方法。
我已经像这样设计了我的图书馆类(在@JoopEggen回答之后):
public class EnumManager<T extends Enum<?> & EnumKind> {
private Class<T> en;
public EnumManager(Class<T> en) {
this.en = en;
}
protected ? getValueFor(String s) {
for(EnumKind ek : en.getEnumConstants()) {
if(s.equals(ek.getText())) {
// I found the enum constant I need... and now?
return ? ;
}
}
}
//...
我应该如何完成该代码?
是的,这是安全的,因为Number[]
是Integer[]
的超类(与List<Number>
并非 List<Integer>
的超类相反)。
因此,如果所宣称的组件类型tt
(声明的类型的元件中的tt
)实现EnumKind
,这种元件的阵列延伸EnumKind[]
因此,这是安全的:
EnumKind[] tt = (EnumKind[]) t.getEnumConstants(); // Casting to superclass: OK
您不会收到任何警告,因为这是安全的,并且永远不会收到ClassCastException
。
要使用.getText
T也必须“扩展” EnumKind。 枚举包装器不提供此功能。
public static class MyC<T extends Enum<?> & EnumKind> {
public void f(T t) {
System.out.println("-> " + t.getText());
}
}
在上方可以看到extends CLASS & INTERFACE
。 额外的限制必须是接口。
问题编辑后:
protected T getValueFor(String s) {
for (T t : en.getEnumConstants()) {
if (s.equals(ek.getText())) {
return t;
}
}
}
使用静态HashMap可能更好。
恐怕整个代码可能会过度设计。 遵循带有太多工件的简单设计会更好。
您想要类似AbstractEnum的东西,
public enum EnumABC {
A("a"), B("b"), C("c");
private static final Map<String, EnumABC> textToEnum = new HashMap<>();
static {
for (EnumABC value : values()) {
EnumABC oldValue = textToEnum.put(value.text, value);
if (oldValue != null) {
throw new IllegalArgumentException(
String.format("Enum %s: same value %s for %s and %s",
value.getClass().getName(),
value.text,
oldValue,
value));
}
}
}
public static EnumABC fromText(String text) {
EnumABC value = textToEnum.get(text);
return value;
}
private final String text;
private EnumABC(String text) {
this.text = text;
}
}
祝好运。
更简单:
@Override
public String getText() {
String s = toString();
return "#" + s.replace('_', ' ') + "#";
}
通用方法如何:
static <T extends Enum<T> & EnumKind> T helper(Class<T> t, String s) {
EnumKind[] tt = t.getEnumConstants();
// do what you need to do here
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.