我设计了一个方法的参数,对于一个必须处理泛型枚举的类(我的意思是,该类可以是库的一部分,用户将使用用户定义的枚举提供该类方法,正在设计的类不知道其特定类型 - 让我们将此类称为“库类”。)
我希望尽可能在语法上约束该参数类型,以便只允许正确的类型。
我的要求是类型必须是实现特定接口的枚举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
)会被编译器拒绝,这就是我想要的行为。
现在,在我的方法体内,我可以成功地做到:
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 ? ;
}
}
}
//...
我该如何填写该代码?
答案 0 :(得分:0)
是的,它是安全的,因为Number[]
是Integer[]
的超类(与List<Number>
相反而不是是{{1}的超类})。
因此,如果声明的组件类型List<Integer>
(tt
的元素的声明类型)实现tt
,则此类元素的数组会扩展EnumKind
,因此这是安全
EnumKind[]
您没有收到任何警告,因为这是安全的,您永远不会得到EnumKind[] tt = (EnumKind[]) t.getEnumConstants(); // Casting to superclass: OK
。
答案 1 :(得分:0)
使用.getText
T必须&#34;延伸&#34; EnumKind也是。 Enum包装器不提供此功能。
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('_', ' ') + "#";
}
答案 2 :(得分:0)
通用方法怎么样:
static <T extends Enum<T> & EnumKind> T helper(Class<T> t, String s) {
EnumKind[] tt = t.getEnumConstants();
// do what you need to do here
}