Java 方法可以返回枚举类型吗?

8
我可能错了,但我猜测从为什么枚举不能在方法中声明?可知,由于Java中的枚举无法在本地声明,因此对于一个方法返回Enum类型会有问题。我可以声明一个方法应该返回一个Enum(见下文),但如何实现这样的方法以返回除null或在方法外声明的Enum引用之外的任何内容呢?我的第一反应是探索使用泛型来解决这个问题,但如果SO社区能帮助我避免死路,我想避免这种情况。
private Enum resources() {
    return null;
}

你想返回一个 Enum 类型,还是一个 Enum 值? - jjnguy
我不确定问题的标题是否最合适。你实际想做什么? - Pascal Thivent
抱歉造成困惑,我在尝试实现某些功能时可能会犯错(我的思维在午后开始变得混乱),但我认为我希望拥有一个返回通用枚举值的方法,而不是枚举类中的一个成员。 - Dexygen
1
你不能这样做,但是你可以返回枚举的所有值。 - Dean Povey
7个回答

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(),但您已经明白了思路。)

请问能否添加如何使用这个类的说明? - msysmilu
1
获取值数组的方法是 values = enumClass.getEnumConstants() - newacct
就像我说的那样,这只是一个虚构的例子。 :) - David Moles

4
Java的枚举类型是类型安全的,这也是它们被设计的主要目的。因此,你不会返回一个枚举类型(这是非常不好的),而是返回你定义的实际类型,比如"Suit",它就像一个类一样。"Suit"有4个枚举实例。
如果你期望得到一个"Suit",那么返回一个值为7的"Rank"有什么用呢?这会破坏一切!
此外,如果你传递一个枚举或一些通用值,你无法调用它的方法。类型安全的枚举最酷的事情是,你可以获取一个"Suit"并调用"Suit.getColor()",完全可以期望得到该套装的颜色。你还可以拥有一个ranksHigherThan(Suit s),它可能满足:
assertTrue(SPADES.ranksHigherThan(HEARTS));

或者,更重要的是:
suit1.ranksHigherThan(suit2);

(假设两者均传入,且您不知道它们是什么)

类型安全确实非常棒(尽管一开始可能会感到有些不舒服),请拥抱它。


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

您可以添加其他方法到接口中以提供更多功能。


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
实际上,我不需要这段代码;似乎这根本不是一个正常的事情 :) - 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
    }
}

我不太确定你在这里能获得什么好处,尽管如果你谈论不同的枚举集和它们的元素,那么这可能是有益的。

如果你谈论的是Enum类(即Iterator的前身),据我所知它还没有泛型化,因此我不确定泛型会在这里有多大帮助。


1

您可以通过名称引用枚举的值,例如Suit.SPADES。

您可以使用values()方法遍历所有值并选择其中一个值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接