[英]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.