Могут ли методы Java возвращать перечисление типов?

Я могу ошибаться, но я предполагаю, что от почему перечисления не могут быть объявлены локально в методе? что, поскольку перечисление в Java не может быть объявлено локально, что поэтому для метода проблематично возвращать перечисление типа? Я могу объявить, что метод должен возвращать перечисление (см. ниже), но как тогда реализовать такой метод, чтобы вернуть что-либо, кроме null, или ссылку на перечисление, объявленное вне метода? Мой первый наклон будет расследовать использование дженериков для этого, но я хотел бы избежать каких-либо тупиков, если сообщество SO может помочь мне избежать их.

private Enum resources() {
    return null;
}

7 ответов


Я думаю, вы правы, он только сможет либо вернуться null или Enum объявлена где-то еще. Но вам не обязательно указывать это "что-то еще" во время компиляции.

  class EnumEnumerator<T extends Enum<T>> implements Iterable<T> {
    private final Class<T> enumClass;

    public EnumEnumerator(Class<T> enumClass) {
      this.enumClass = enumClass;
    }

    public Iterator<T> iterator() {
      T[] values = enumClass.getEnumConstants();
      return Arrays.asList(values).iterator();
    }
  }

позже вы вызываете его, специализируя универсальный конструктор и передавая в класс перечисления, который вас интересует:

class EnumEnumeratorDemo {
    enum Foo {
        BAR, BAZ, QUX;
        @Override public String toString() {
            return name().toLowerCase();
        }
    }

    public static void main(String[] args) {
        for (Foo f : new EnumEnumerator<Foo>(Foo.class)) {
            System.out.println(f);
        }
    }
}

(очевидно, что это надуманный пример, и в реальной жизни, вы должны просто вызвать функцию Foo.values(), но вы получаете идею.)


весь смысл того, как Java делает перечисления, заключается в том, что они typesafe-поэтому вы не вернули бы перечисление (это было бы double-plus ungood), вместо этого вы возвращаете фактический тип, который вы определяете (например, "костюм"), который действует так же, как класс. Костюм имеет 4 "перечисленных" экземпляра.

Если бы вы ожидали "костюм", что хорошего было бы вернуть" ранг " 7? Это все сломает!

также, если вы передали "перечисление" или какое-то общее значение, вы не могли вызвать методы на нем. Самое крутое в Typesafe Enums заключается в том, что вы можете просто получить "костюм" и позвонить "костюм.getColor () " и полностью ожидать, чтобы получить цвет этого костюма. Вы также можете иметь ranksHigherThan (костюм s) , который может выполнить:

assertTrue(SPADES.ranksHigherThan(HEARTS));

или, что более важно:

suit1.ranksHigherThan(suit2);

(предполагая, что они оба были переданы, и вы не знаете, что они такое)

безопасность типа действительно удивительна (хотя сначала она чувствует себя немного неудобно), примите ее.


все перечисления реализуют перечисление интерфейса, поэтому вы можете написать метод, который возвращает перечисление таким образом. Но этот метод вернет одно значение перечисления. Невозможно вернуть общее значение, которое охватывает все перечисление (кроме возврата класса и выполнения отражения). Однако вы можете вернуть все значения перечисления, которые более или менее соответствуют тому, что вы хотите.

enum Resources { ONE, TWO, THREE }
private Enum<?>[] resources() {
    return Resources.values();
}

одним из преимуществ этого подхода является то, что вы можете возвращать больше или меньше значений для пример:

enum Resources { ONE, TWO, THREE }
enum MoreResources { UN, DEUX, TROIS }
private Enum<?>[] resources() {
    List<Enum<?>> resources = new ArrayList<Enum<?>>();
    resources.addAll(Arrays.asList(Resources.values());
    resources.addAll(Arrays.asList(MoreResources.values());
    return resources.toList(new Enum<?>[] {});
}

еще лучший подход, который является более безопасным является для перечисления процентов реализуйте общий интерфейс, например

public interface Resources {}
enum SomeResources implements Resources { ONE, TWO, THREE }
enum MoreResources implements Resources { UN, DEUX, TROIS }
private Resources[] resources() {
    List<Resources> resources = new ArrayList<Resources>();
    resources.addAll(Arrays.asList(Resources.values());
    resources.addAll(Arrays.asList(MoreResources.values());
    return resources.toList(new Resources[] {});
}

вы можете добавить дополнительные методы к интерфейсу для обеспечения большей функциональности.


чего вы пытаетесь достичь? Это способ вернуть Enum:

public class Test
{
    public static void main(String args[])
    {
        System.out.println(doit());
    }

    public enum Foo {
        BAR,
        BAZ;
    }
    public static Enum doit() {
        return Enum.valueOf(Foo.class,"BAR");
    }
}

но, я предполагаю, что это не то, что вы собираетесь?


Да, это определенно возможно.

private Enum getRetentionPolicy() {
    return java.lang.annotation.RetentionPolicy.SOURCE;
}

Если ваш вопрос о объявления перечисления, вы можете объявить их:

  • в своем собственном файле java, похожем на верхний уровень class;
  • в файле java, принадлежащем другому классу, похожему на статический внутренний class;

не совсем уверен, какова ваша цель, но если вы хотите вернуть обобщенный метод (т. е. тот, который будет переопределен), у вас может быть что-то вроде следующего:

public class MyEnumClass<T extends Enum<T>> {
    public T resources() {
        //do stuff here
    }
}

Не совсем уверен, что вы получите там, хотя это может быть полезно, если вы говорите о разных комплектов перечислений и их элементов.

Если вы говорите о классе перечисления (т. е. перкурсор к итератору), насколько я знаю, он не был обобщен, поэтому я не уверен дженерики здесь очень помогут.


вы можете ссылаться на значение перечисления по его имени, например, костюм.ПИКИ.

вы можете перебирать все значения с помощью метода values () и выбрать одно из значений.