【问题标题】:How do I create a generic method to return an array of the enum values instead of its constants?如何创建一个泛型方法来返回枚举值数组而不是其常量?
【发布时间】:2018-11-21 06:38:09
【问题描述】:

我有一个枚举,其描述为字符串。这是枚举。

public enum tabs
{
    A("Actual data"),
    B("Bad data"),
    C("Can data"),
    D("Direct data");

    private String description;
    tabs(String desc)
    {
        this.description = desc;
    }


    public String getDescription()
    {
        return this.description;
    }
}

现在,如果我需要 A 的数据,我会这样做

tabs.A.description

我正在创建一个通用方法来返回值。

我已经设法利用下面的通用方法来接受枚举类型作为参数。 它返回枚举常量的数组。 但我实际上希望它返回一个值数组。即 {"Actual data", "Bad data", "Can data", "Direct data"}。

public static String[] getActualTabs(Class<? extends Enum<?>> e) 
{
    return Arrays.stream(e.getEnumConstants()).map(Enum::name).toArray(String[]::new);
}

我有哪些选择来实现这一目标?

【问题讨论】:

  • 改进建议:在Java中,类是大写的,例如String、Integer、Class。枚举只是一个常量类,所以tabs 应该是Tabs

标签: java generics enums


【解决方案1】:

您可以传递一个映射器Function 将枚举常量映射到Strings:

public static <T extends Enum<T>> String[] getActualTabs(Class<T> e, Function<? super T, String> mapper) 
{
    return Arrays.stream(e.getEnumConstants()).map(mapper).toArray(String[]::new);
}

用法:

System.out.println(Arrays.toString(getActualTabs(tabs.class,tabs::getDescription)));

输出:

[Actual data, Bad data, Can data, Direct data]

【讨论】:

  • 这绝对有效。谢谢。我确实有一个相关的问题。假设我必须传入不同的枚举。那么 mapper 参数会变成什么? tabs.class 是一个枚举。假设我也有 servers.class 作为另一个枚举。而且我必须为 mapper 参数传递一个泛型。我该如何处理这种情况?如何将 tabs:getDescription 也转换为泛型?我的意思是我想摆脱硬编码的 tabs::getDescription 并使它可以传入任何枚举...有点像:::getDescription
  • @SteroidKing666 使用映射器Function 参数为您提供了更大的灵活性。对于tabs,您想要获取getDescription() 的值。对于其他一些枚举,您可能想要获取不同属性的值(例如getColor())。如果你的server枚举也有getDescription(),你可以通过server::getDescription。如果您只想支持getDescription() 方法,您可以使用类似 Mureinik 的答案(即要求枚举实现某个接口)。
  • @SteroidKing666 如果您担心必须在方法引用中指定枚举名称,则可以使用 lambda 表达式:将 tabs::getDescription 替换为 e -&gt; e.getDescription()。这将适用于任何具有返回 StringgetDescription 方法的枚举。
  • 好的,所以 getActualTabs(enumName,e->getDescription()) 应该可以工作。如果 enumName 是 Class> class1 ?也就是说,我接受 class1 作为方法的通用枚举。然后将该通用枚举 class1 传递给 getActualTabs。因为那样 getActualTabs(class1,e->getDescription()) 将不起作用。
  • @Eran 是我自己发现的:.getEnumConstants() 是所有Class&lt;&gt;es 的方法。如果它不是枚举类型,它是just returns null,所以你的函数会抛出一个 NPE。因此,虽然&lt;T extends Enum&lt;T&gt;&gt; 并不是绝对必要的,但最好拥有它,因为它可以防止 NPE 被滥用。
【解决方案2】:

我首先将getDescription 拉出一个接口,并确保您项目的所有枚举都实现它:

public interface HasDescription {
    String getDescription();
}

然后,在你的通用方法中使用它:

public static String[] getActualTabs(Class<? extends Enum<?> & HasDescription> e) {
    return Arrays.stream(e.getEnumConstants())
                 .map(HasDescription::getDescription)
                 .toArray(String[]::new);
}

【讨论】:

  • 我明白了。但不知何故,我收到以下错误: Class 类型的参数数量不正确;它不能用参数参数化 ,Script1.HasDescription>。我的枚举和 HasDescription 接口都在同一个类中。
  • 我认为你必须用泛型类型变量重新编写它,因为通配符只能有一个类型绑定(即Class&lt;? extends Enum&lt;?&gt; &amp; HasDescription&gt; e 不通过编译)
【解决方案3】:

两个答案都很漂亮。

但还有另一种变体可能更优越,因为它的使用范围更广:

public static <T> String[] getActualTabs(T[] values, Function<? super T, String> mapper) {
    return Arrays.stream(values)
                 .map(mapper)
                 .toArray(String[]::new);
}

public static <T extends HasDescription> String[] getActualTabs(T[] values) {
    return Arrays.stream(values)
                 .map(HasDescription::getDescription)
                 .toArray(String[]::new);
    // or just: return getActualTabs(values, HasDescription::getDescription);
}

这种实现的好处是我们不必乱用反射。

相反,您可以这样称呼它们:

String[] tabs1 = getActualTabs(Tabs.values())
String[] tabs2 = getActualTabs(Tabs.values(), Tabs::getDescription)

请注意,重命名函数可能很有用,例如。 G。 getStringifiedValues()toDescriptions()

免责声明:未经测试,但应该可以工作,恕我直言。

【讨论】:

  • 如果我有另一个名为 private void verifyTabData(Class extends Enum>> class1) 的通用方法包含 getActualTabs 方法,我将如何实现?我将不同的枚举集传递给这个根方法。
  • @SteroidKing666 如果唯一不同的是值列表,您可以在任何地方使用{EnumType}.values()。如果您受限于此签名,您可以致电.values() resp。 .getEnumConstants() 在这个函数中。或者你会诉诸原来的替代方案,以免完全破坏原来的概念。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多