Могут ли методы Java возвращать тип Enum? - PullRequest
7 голосов
/ 16 сентября 2009

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

private Enum resources() {
    return null;
}

Ответы [ 7 ]

8 голосов
/ 17 сентября 2009

Я думаю, что вы правы, он только сможет вернуть 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();
    }
  }

Позже вы вызываете его, специализируя общий конструктор и передавая интересующий вас класс enum:

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 ​​(), но вы поняли идею.)

3 голосов
/ 16 сентября 2009

Весь смысл того, как Java делает Enums, заключается в том, что они безопасны от типов - поэтому вы не будете возвращать Enum (это было бы двойным плюсом), вместо этого вы возвращаете фактический тип, который вы определили (например, «Suit») который действует так же, как класс. Костюм имеет 4 "перечислимых" экземпляра.

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

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

assertTrue(SPADES.ranksHigherThan(HEARTS));

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

suit1.ranksHigherThan(suit2);

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

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

3 голосов
/ 16 сентября 2009

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

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[] {});
}

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

2 голосов
/ 16 сентября 2009

Чего ты пытаешься достичь? Это способ вернуть 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");
    }
}

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

1 голос
/ 16 сентября 2009

Вы можете ссылаться на значение перечисления по его имени, например, Suit.SPADES.

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

1 голос
/ 16 сентября 2009

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

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

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

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

1 голос
/ 16 сентября 2009

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

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

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

  • в своем собственном Java-файле, похожем на файл верхнего уровня class;
  • внутри Java-файла, принадлежащего другому классу, аналогично статическому внутреннему class;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...