5

枚举构造函数必须是私有或包默认值,并且不允许使用受保护或公共访问修饰符。为什么这样

4

4 回答 4

5

因为根据定义,枚举具有一组固定的实例,这些实例在枚举本身中声明和构造。因此,从枚举类本身外部使用构造函数是没有意义的。

而且 AFAIK,枚举构造函数始终是显式或隐式私有的。

于 2012-07-11T14:59:55.293 回答
3

来自Java 教程

枚举类型的构造函数必须是包私有或私有访问。它会自动创建在枚举体开头定义的常量。您不能自己调用​​枚举构造函数。

能够创建枚举的新实例是没有意义的,因此语言会阻止您这样做!

于 2012-07-11T14:58:37.940 回答
1

枚举并不意味着(由您)实例化。

http://docs.oracle.com/javase/tutorial/reflect/special/enumTrouble.html

提示:尝试显式实例化枚举是编译时错误,因为这会阻止定义的枚举常量是唯一的。此限制也在反射代码中强制执行。尝试使用其默认构造函数实例化类的代码应首先调用 Class.isEnum() 以确定该类是否为枚举。

于 2012-07-11T14:58:24.023 回答
0

您不能动态扩展枚举的原因是实例化的值被编译为 Class 对象的字节码:

public T[] getEnumConstants()
    Returns the elements of this enum class or null if this Class object does not
    represent an enum type.

因此,任何构造新实例的尝试都无法传递给实际的 Class,因为 Class 对象无法更改。如果你想要这种行为,你必须自己模拟它,并给它某种唯一的值来表示每个值,然后有一个序数计数器,最后是一个静态映射(或其他结构)来保存所有值.

public class MyEnum {
  private static AtomicInteger nextOrdinal = new AtomicInteger(0);
  private static Map<Integer, MyEnum> instances =
      new HashMap<Integer, MyEnum>();

  private int ordinal;
  private String name;

  public MyEnum(String name) {
     super();
     this.ordinal = nextOrdinal.incrementAndGet();
     this.name = name;
     instances.put(Integer.valueOf(this.ordinal), this);
  }

  public String name() {
     return name;
  }

  public int ordinal() {
     return ordinal;
  }

  public static Set<MyEnum> getEnumConstants() {
     return Collections.unmodifiableSet(instances.values());
  }


  public static MyEnum fromInt(int ordinal) {
     return instances.get(Integer.valueOf(ordinal));
  }

  public static MyEnum fromString(String name) {
     for (MyEnum val : instances.values()) {
         if (val.name().equals(name)) {
             return val;
         }
     }
     return null;
  }

}

您可能还需要一个 .equals 和 .hashcode 方法,以及防止多次使用相同的名称(如果您有重复的名称,您可以在构造函数中执行此操作并抛出 IllegalStateException 或其他东西)。

于 2012-07-11T15:58:04.590 回答