![](/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.