Can Java methods return type Enum?
Asked Answered
N

7

8

I could be wrong but I'm guessing from Why can't enums be declared locally in a method? that, since an enum in Java cannot be declared locally, that therefore it is 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;
}
Negotiate answered 15/9, 2009 at 20:48 Comment(4)
You want to return an Enum type, or an Enum value?Fulgurate
I'm not sure the title of the question is the most appropriate. What do you actually want to do?Zane
Sorry for the confusion, and I could certainly be mistaken in what I'm trying to acheive (my thinking starts going awry in the late afternoon) but I thought I might like to have a method return a generic Enum not a member from an Enum.Negotiate
You can't do that, but you can return all the values of an enum.Interfluent
P
8

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

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

Later, you invoke it by specializing the generic constructor and passing in the enum class you're interested in:

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

(Obviously this is a contrived example and in real life you should just call Foo.values(), but you get the idea.)

Photometer answered 17/9, 2009 at 10:46 Comment(3)
can you please add how to use this class?Hypogeum
p.s. for getting the array of values you can just do values = enumClass.getEnumConstants()Quassia
As I said, it's a contrived example. :)Photometer
B
4

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.

Boor answered 15/9, 2009 at 21:35 Comment(0)
I
3

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.

Interfluent answered 15/9, 2009 at 21:1 Comment(0)
T
2

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?

Transplant answered 15/9, 2009 at 20:56 Comment(1)
Actually, I don't want any of this code; seems like an odd thing to be doing at all :)Transplant
A
1

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;
Audrit answered 15/9, 2009 at 20:58 Comment(0)
M
1

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.

Monongahela answered 15/9, 2009 at 20:58 Comment(0)
P
1

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.

Phytogeography answered 15/9, 2009 at 20:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.