[英]In Java how do write code to loop round an arbitary enum?
如何編寫代碼循環任意枚舉?
因此,在下面的代碼中使用枚舉作為提供創建Html select循環的值,但是我看不到如何將枚舉傳遞給方法,或者如何訪問標准的.values()
和.ordinal()
方法。 所以目前我已經對特定的枚舉RenameFileOptions進行了硬編碼,但是我想使用任何枚舉,我可以解析枚舉類,例如RenameFileOptions.class
但仍然如何訪問.name()
.values()
和.ordinal()
public ContainerTag addCombo(UserOption userOption, int selectedValue)
{
return div(
label(userOption.getLabel().getMsg())
.withTitle(userOption.getTooltip().getMsg()),
select(
each(Arrays.asList(RenameFileOptions.values()),
next ->
iffElse(next.ordinal()==selectedValue,
option(next.name()).attr(Html.SELECTED, Html.SELECTED).withValue(String.valueOf(next.ordinal())),
option(next.name()).withValue(String.valueOf(next.ordinal()))
)
))
.withName(userOption.getOption())
);
}
更新由於似乎沒有辦法以一種輕松的方式實現這一目標,所以我向每個枚舉添加了一個getOptions()方法,這就是發送給我的addCombo方法的內容。 這意味着我必須重復執行我不喜歡做的代碼,但這意味着addCombo()方法可以按要求工作,並且通過不引入困難的語法來使代碼更易於理解。
public enum RenameFileOptions implements OptionList
{
NO(TextLabel.RENAME_FILE_OPTION_NO),
YES_IF_MATCHED_TO_RELEASE(TextLabel.RENAME_FILE_OPTION_YES_IF_RELEASE_MATCH),
YES_IF_MATCHED_TO_RELEASE_OR_SONG(TextLabel.RENAME_FILE_OPTION_YES_IF_RELEASE_OR_SONG_MATCH),
YES_IF_HAS_BASIC_METADATA(TextLabel.RENAME_FILE_OPTION_YES_IF_HAS_METADATA),
YES_FOR_ALL_SONGS(TextLabel.RENAME_FILE_OPTION_YES),
;
private TextLabel label;
RenameFileOptions(TextLabel label)
{
this.label=label;
}
public String getName()
{
return label.getMsg();
}
public String toString()
{
return getName();
}
public static List<NameKey> getOptions()
{
List<NameKey> options = new ArrayList<NameKey>();
for(RenameFileOptions next:RenameFileOptions.values())
{
options.add(new NameKey(next.ordinal(), next.getName()));
}
return options;
}
}
public class NameKey
{
private Integer id;
private String name;
public NameKey(Integer id, String name)
{
this.id =id;
this.name=name;
}
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
您應該使用Class.getEnumConstants()
方法。
因此,您的代碼的中間部分應類似於
each(Arrays.asList(enumClass.getEnumConstants()),
next ->
iffElse(next.ordinal()==selectedValue,
option(next.name()).attr(Html.SELECTED, Html.SELECTED).withValue(String.valueOf(next.ordinal())),
option(next.name()).withValue(String.valueOf(next.ordinal()))
)
))
並且您應該通過Class<? extends Enum<?>> enumClass
在方法參數中Class<? extends Enum<?>> enumClass
。
您可以使用EnumSet.allOf()
:
for(MyType t : EnumSet.allOf(MyType.class)) {
doSomethingWith(t);
}
...或使用Java 8 lambda:
EnumSet.allOf(MyType.class).forEach(
t -> doSomethingWith(t)
);
盡管是Set
,但EnumSet
的文檔指出其迭代器產生的值“以其自然順序 (聲明枚舉常量的順序)”
對於任意枚舉類:
<T extends Enum<T>> void loopAroundEnum(Class<T> enumType) {
EnumSet.allOf(enumType).forEach(
val -> doSomethingWith(val) // val is of type T
);
}
盡管Java習慣是不進行過早優化,但值得一提的是,與使用MyType.getEnumConstants()
返回的MyType[]
數組相比, EnumSet
可能在速度和內存消耗上都更有效率。
從EnumSet
的Javadoc:
枚舉集在內部表示為位向量。 這種表示非常緊湊和高效。 該類的時空性能應足夠好,可以用作傳統的基於int的“位標志”的高質量,類型安全的替代方法。
由於Enum是基類,因此您需要將Class傳遞給枚舉:
public <E extends Enum<E>> void method(Class<E> type) {
E[] values = type.getEnumConstants();
}
當然,Class會測試它是否為枚舉。 如果沒有枚舉類,則返回null。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.