views:

1388

answers:

7

I could be wrong but I'm guessing from this previous SO post that, since an enum in Java cannot be declared locally, that therefore it is therefore problematic for a method to return type Enum? I can declare that a method should return an Enum (see below) but how would one then go about implementing such a method to return anything other than null, or a reference to an Enum declared outside the method? My first inclination would be to investigate using Generics for this but I'd like to avoid any deadends if the SO community can help me avoid them.

private Enum resources() {
    return null;
}
+1  A: 

What are you trying to accomplish? This is a way to return an 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");
    }
}

But, I'm guessing this is not what you are going for?

davetron5000
You want `Enum<?>`.
Tom Hawtin - tackline
Actually, I don't want any of this code; seems like an odd thing to be doing at all :)
davetron5000
+1  A: 

Yes, it definitely is possible.

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

If your question is about declaring Enums, you may declare them:

  • in their own java file, similar to a top-level class;
  • within a java file belonging to another class, similar to a static inner class;
Robert Munteanu
+1  A: 

Not totally sure what your goal is, but if you wanted to return a generified method (i.e. one that would be overridden) you might have something like the following:

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

Not entirely sure what you would gain there, although it can be beneficial if you are talking about different sets of Enums and their elements.

If you are talking about the Enum class (i.e. the percursor to Iterator) as far as I know it has not been generified, so I am not sure generics would help much here.

aperkins
+1  A: 

You can refer to a value of an enum by its name, e.g. Suit.SPADES.

You can iterate over all values by using the values() method and pick one of the values.

starblue
A: 

All enums implement the interface Enum, so you can certainly write a method that returns an enum this way. But this method will return a single enum value. There is no way to return a generic value which encompasses the whole enum (apart from returning the class and doing reflection). You can however return all the enum values which is more or less what you want I think.

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

One benefit of this approach is you can return more or less values for example:

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

An even better approach that is more typesafe is to have the enums of interest implement a common interface e.g.

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

You can add additional methods to the interface to provide more functionality.

Dean Povey
+3  A: 

The entire point of the way Java does Enums is that they are typesafe--so you wouldn't return an Enum (that would be double-plus ungood) instead you return the actual type you define (like "Suit") which acts just like a class. Suit has 4 "Enumerated" instances.

If you were expecting a "Suit", what good would it be to return a "Rank" of 7? It would break everything!

Also if you passed an "Enum" or some generic value, you couldn't call methods on it. The coolest thing about TypeSafe Enums is that you can just get a "Suit" and call "Suit.getColor()" and fully expect to get the color of that suit. You could also have a ranksHigherThan(Suit s) which might fulfill:

assertTrue(SPADES.ranksHigherThan(HEARTS));

Or, more importantly:

suit1.ranksHigherThan(suit2);

(assuming they were both passed in and you don't know what they are)

Type safety is really amazing (even though it feels a little uncomfortable at first), embrace it.

Bill K
+1  A: 

I think you're correct, it's only going to be able to either return null or an Enum declared somewhere else. But you don't necessarily have to specify that "something else" at compile time.

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

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

    @SuppressWarnings("unchecked")
    public Iterator<T> iterator() {
      try {
        T[] values = (T[]) enumClass.getDeclaredMethod("values").invoke(null);
        return Arrays.asList(values).iterator();
      } catch (Exception e) { 
        // Ignore like six different reflection-related exceptions
        throw new IllegalStateException(e);
      }
    }
  }
David Moles