以多态方式将Java枚举值转换为字符串列表
我有一些助手方法,可以将枚举值转换为适合HTML以多态方式将Java枚举值转换为字符串列表,java,generics,reflection,enums,polymorphism,Java,Generics,Reflection,Enums,Polymorphism,我有一些助手方法,可以将枚举值转换为适合HTML元素显示的字符串列表。我想知道是否有可能将它们重构为一个多态方法 这是我现有方法之一的示例: /** * Gets the list of available colours. * * @return the list of available colours */ public static List<String> getColours() { List<String> colours = new Arra
元素显示的字符串列表。我想知道是否有可能将它们重构为一个多态方法
这是我现有方法之一的示例:
/**
* Gets the list of available colours.
*
* @return the list of available colours
*/
public static List<String> getColours() {
List<String> colours = new ArrayList<String>();
for (Colour colour : Colour.values()) {
colours.add(colour.getDisplayValue());
}
return colours;
}
/**
*获取可用颜色的列表。
*
*@返回可用颜色列表
*/
公共静态列表getcolors(){
列表颜色=新的ArrayList();
用于(颜色:color.values()){
colors.add(color.getDisplayValue());
}
返回颜色;
}
我对Java泛型还是相当陌生,所以我不确定如何将泛型枚举传递给该方法,并在for循环中使用它
请注意,我知道所讨论的枚举都将具有getDisplayValue
方法,但不幸的是,它们不共享定义它的公共类型(我不能介绍一个),因此我猜必须以反射方式访问它
提前感谢您的帮助。(对不起,这里是C#。我没有看到这个问题是针对Java的。)
public字符串[]GetValues()
{
返回Enum.GetNames(typeof(T));
}
当然,对于Java,所有枚举类型仍然继承自Java.util.enum,因此您可以编写:
public string[] getValues<T extends Enum<T>>()
{
// use reflection on T.class
}
public字符串[]getValues()
{
//在T类上使用反射
}
由于java.util.Enum实际上没有实现values(),我认为反射是唯一的方法。这里有两件事可以做。第一种(更简单,因此更好)方法是让getStrings()方法获取某个接口的列表,并让枚举实现该接口:
public interface DisplayableSelection {
public String getDisplayValue();
}
private static List<String> getStrings (Collection<DisplayableSelection> things) {
List<String> retval = new ArrayList<String>();
for (DisplayableSelection thing : things) {
retval.add(thing.getDisplayValue());
}
}
private static List<String> getColours () {
return getStrings(Colour.values());
}
公共界面可显示选择{
公共字符串getDisplayValue();
}
私有静态列表getStrings(集合内容){
List retval=new ArrayList();
用于(可显示选择对象:对象){
添加(thing.getDisplayValue());
}
}
私有静态列表getcolors(){
返回getStrings(color.values());
}
如果您在内部真正关心类型是一个枚举,那么您还可以使用这样一个事实,即所有枚举类型都会自动为内置类型枚举子类化。因此,以您的示例为例(免责声明:我认为这可以编译,但实际上还没有尝试过):
公共接口DisplayableEnum{
公共字符串getDisplayValue();
}
私有静态列表getDisplayValues(类pClass){
List retval=new ArrayList();
for(DisplayableSelection对象:pClass.getEnumConstants()){
添加(thing.getDisplayValue());
}
}
私有静态列表getcolors(){
返回getStrings(color.class);
}
如果您想做一些特别需要枚举的事情(例如,出于某种原因使用枚举映射或枚举集),则第二种形式非常有用;否则,我将使用第一种方法(因为使用该方法,您还可以使用非枚举类型,或者仅使用枚举的子集)
请注意,我知道
问题是所有人都会有这样的想法
getDisplayValue方法,但
不幸的是,他们没有共同的目标
定义它的公共类型(以及
不能介绍一个),所以我猜
必须被访问
深思熟虑地
你猜对了。另一种方法是通过返回display值让enum all实现
toString()
,但是如果您不能让它们实现接口,那么我认为这也不可能。您可以在某些实用程序类中使用此方法:
public static <T extends Enum<T>> List<String> getDisplayValues(Class<T> enumClass) {
try {
T[] items = enumClass.getEnumConstants();
Method accessor = enumClass.getMethod("getDisplayValue");
ArrayList<String> names = new ArrayList<String>(items.length);
for (T item : items)
names.add(accessor.invoke(item).toString()));
return names;
} catch (NoSuchMethodException ex) {
// Didn't actually implement getDisplayValue().
} catch (InvocationTargetException ex) {
// getDisplayValue() threw an exception.
}
}
公共静态列表GetDisplayValue(类enumClass){
试一试{
T[]items=enumClass.getEnumConstants();
方法访问器=enumClass.getMethod(“getDisplayValue”);
ArrayList名称=新的ArrayList(items.length);
对于(T项:项)
name.add(accessor.invoke(item.toString());
返回姓名;
}catch(NoSuchMethodException-ex){
//实际上没有实现getDisplayValue()。
}捕获(调用TargetException ex){
//getDisplayValue()引发了异常。
}
}
来源:我会使用一个
java.util.ResourceBundle
和一个绑定文件,该绑定文件映射到枚举的toString
(可能还有类名)值,这样您的代码就会变成:
bundle.getString(enum.getClass().getName() + enum.toString());
使用方法很简单:
static <T extends Enum<T>> List<String> toStringList(Class<T> clz) {
try {
List<String> res = new LinkedList<String>();
Method getDisplayValue = clz.getMethod("getDisplayValue");
for (Object e : clz.getEnumConstants()) {
res.add((String) getDisplayValue.invoke(e));
}
return res;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
静态列表到字符串(类clz){
试一试{
List res=new LinkedList();
方法getDisplayValue=clz.getMethod(“getDisplayValue”);
对于(对象e:clz.getEnumConstants()){
res.add((String)getDisplayValue.invoke(e));
}
返回res;
}捕获(例外情况除外){
抛出新的运行时异常(ex);
}
}
这不是完全类型安全的,因为您可以拥有一个没有
getDisplayValue
方法的枚举。我建议您这样做:
首先是某个实用程序类中的帮助器方法和静态内部类:
@SuppressWarnings("unchecked")
public static <T> T generateProxy(Object realObject, Class<?>... interfaces) {
return (T) Proxy.newProxyInstance(realObject.getClass().getClassLoader(), interfaces, new SimpleInvocationHandler(realObject));
}
private static class SimpleInvocationHandler implements InvocationHandler {
private Object invokee;
public SimpleInvocationHandler(Object invokee) {
this.invokee = invokee;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
method = invokee.getClass().getMethod(method.getName(), method.getParameterTypes());
if (!method.isAccessible()) {
method.setAccessible(true);
}
try {
return method.invoke(invokee, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
}
@SuppressWarnings(“未选中”)
公共静态T generateProxy(对象realObject、类…接口){
return(T)Proxy.newProxyInstance(realObject.getClass().getClassLoader(),接口,新SimpleInvocationHandler(realObject));
}
私有静态类SimpleInvocationHandler实现InvocationHandler{
私有对象被调用方;
公共SimpleInvocationHandler(对象被调用者){
this.invokee=invokee;
}
公共对象调用(对象代理、方法、对象[]参数)
扔掉的{
method=invokee.getClass().getMethod(method.getName(),method.getParameterTypes());
如果(!method.isAccessible()){
方法setAccessible(true);
}
试一试{
invoke(被调用方,参数);
}捕获(调用TargetException e){
抛出e.getTargetException();
}
}
}
然后把它和你放在一起
static <T extends Enum<T>> List<String> toStringList(Class<T> clz) {
try {
List<String> res = new LinkedList<String>();
Method getDisplayValue = clz.getMethod("getDisplayValue");
for (Object e : clz.getEnumConstants()) {
res.add((String) getDisplayValue.invoke(e));
}
return res;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
@SuppressWarnings("unchecked")
public static <T> T generateProxy(Object realObject, Class<?>... interfaces) {
return (T) Proxy.newProxyInstance(realObject.getClass().getClassLoader(), interfaces, new SimpleInvocationHandler(realObject));
}
private static class SimpleInvocationHandler implements InvocationHandler {
private Object invokee;
public SimpleInvocationHandler(Object invokee) {
this.invokee = invokee;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
method = invokee.getClass().getMethod(method.getName(), method.getParameterTypes());
if (!method.isAccessible()) {
method.setAccessible(true);
}
try {
return method.invoke(invokee, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
}
interface DisplayableEnum {
String getDisplayValue();
}
private static List<String> getFromEnum(Class<? extends Enum<?>> displayableEnum) {
List<String> ret = new ArrayList<String>();
for (Enum e : displayableEnum.getEnumConstants()) {
DisplayableEnum de = generateProxy(e, DisplayableEnum.class);
ret.add(de.getDisplayValue());
}
return ret;
}
public static interface Displayer<T> {
String displayName(T t);
}
public static <T> List<String> getDisplayNames(Iterable<? extends T> stuff,
Displayer<T> displayer) {
List<String> list = new ArrayList<String>();
for (T t : stuff) {
list.add(displayer.displayName(t));
}
return list;
}
enum Foo {
BAR("BAR"), BAZ("BAZ");
private final String displayName;
private Foo(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return displayName;
}
}
public static void main(String[] args) {
Displayer<Foo> fooDisplayer = new Displayer<Foo>() {
public String displayName(Foo foo) {
return foo.getDisplayName();
}
};
System.out.println(getDisplayNames(Arrays.asList(Foo.BAR, Foo.BAZ),
fooDisplayer));
}
public static <T extends Enum<T>> List<String> getDisplayValues(
Class<T> enumClass) {
try {
T[] items = enumClass.getEnumConstants();
Method accessor = enumClass.getMethod("toString");
ArrayList<String> names = new ArrayList<String>(items.length);
for (T item : items)
names.add(accessor.invoke(item).toString());
return names;
} catch (NoSuchMethodException ex) {
// Didn't actually implement getDisplayValue().
Log.e(TAG, "getDisplayValues [" + ex+"]");
} catch (InvocationTargetException ex) {
// getDisplayValue() threw an exception.
Log.e(TAG, "getDisplayValues [" + ex+"]");
} catch (IllegalAccessException ex) {
// getDisplayValue() threw an exception.
Log.e(TAG, "getDisplayValues [" + ex+"]");
}
return null;
}
public static <T extends Enum<T>> Map<T, String> Initialize_Map(Class<T> enumClass) {
Map<T, String> map = new HashMap<T, String>();
for (T val : enumClass.getEnumConstants()) {
map.put(val, val.toString() + (val.toString().equals("ENUM_ELMT") ? " (appended)" : ""));
}
return map;
}