Как создать универсальный метод для возврата массива значений перечисления вместо его констант?

У меня есть перечисление с описаниями как String. Это перечисление.

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

Теперь, если мне нужны данные для А, я просто сделаю

tabs.A.description

Я нахожусь в процессе создания универсального метода для возврата значений.

Мне удалось использовать приведенный ниже универсальный метод, чтобы принять тип enum в качестве аргумента. Возвращает массив перечисляемых констант. Но на самом деле я хочу, чтобы он возвращал массив значений.. т.е. {"Фактические данные", "Неверные данные", "Могут данные", "Прямые данные"}.

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

Какие варианты у меня есть, чтобы достичь этого?

Ответ 1

Вы можете передать сопоставитель Function для отображения перечислений константы INTO String s:

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]

Ответ 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);
}

Ответ 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)

Обратите внимание, что может быть полезно переименовать функции, например, getStringifiedValues() или toDescriptions().

Отказ от ответственности: не проверено, но должно работать, ИМХО.