2009-09-15 2 views
7

Я мог ошибаться, но я догадываюсь от Why can't enums be declared locally in a method? , что, поскольку перечисление в Java не может быть объявлено локально, что поэтому проблематично для метода вернуть тип Enum? Я могу объявить, что метод должен возвращать Enum (см. Ниже), но как же тогда можно было бы реализовать такой метод, чтобы возвращать что-либо, кроме null, или ссылку на Enum, объявленную вне метода? Моя первая склонность состояла в том, чтобы исследовать с помощью Generics для этого, но я хотел бы избежать любых мер, если сообщество SO поможет мне избежать их.Может ли Java-метод возвращать тип Enum?

private Enum resources() { 
    return null; 
} 
+0

Вы хотите вернуть тип «Enum» или значение «Enum»? – jjnguy

+0

Я не уверен, что название вопроса является наиболее подходящим. Что вы на самом деле хотите сделать? –

+0

Извините за замешательство, и я, конечно, мог ошибиться в том, что я пытаюсь добиться (мое мышление начинается в конце дня), но я подумал, что мне может понравиться, что метод возвращает общий элемент Enum * not * из Enum. –

ответ

8

Я думаю, что вы правы, он сможет либо вернуть 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 ​​(), но вы получите эту идею.)

+0

можете ли вы добавить, как использовать этот класс? – msysmilu

+0

сделано-надеюсь, что это помогает. –

+1

стр. для получения массива значений вы можете просто 'values ​​= enumClass.getEnumConstants()' – newacct

2

Что вы пытаетесь достичь? Это способ возвращать 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

Вы хотите 'Enum '. –

+0

На самом деле, я не хочу этого кода; кажется странным, что нужно делать вообще :) – davetron5000

1

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

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

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

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

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

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

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

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

1

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

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

3

Все перечисления реализуют интерфейс 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[] {}); 
} 

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

3

Все, что касается Java, представляет собой то, что они являются типичными - поэтому вы не вернете Enum (это будет double-plus ungood), вместо этого вы вернете фактический тип, который вы определяете (например, «Suit»)), который действует как класс. Костюм имеет 4 экземпляра «Enumerated».

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

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

assertTrue(SPADES.ranksHigherThan(HEARTS)); 

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

suit1.ranksHigherThan(suit2); 

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

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