Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
以多态方式将Java枚举值转换为字符串列表_Java_Generics_Reflection_Enums_Polymorphism - Fatal编程技术网

以多态方式将Java枚举值转换为字符串列表

以多态方式将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

我有一些助手方法,可以将枚举值转换为适合HTML
元素显示的字符串列表。我想知道是否有可能将它们重构为一个多态方法

这是我现有方法之一的示例:

/**
 * 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;       
}