今天我浏览了这个网站上的一些问题,我发现一个枚举被用于单例模式,据称线程安全的好处,这种解决方案。

我从来没用过枚举,而且我已经用Java编程好几年了。显然,他们改变了很多。现在他们甚至在自己内部完全支持OOP。

为什么我应该在日常编程中使用enum ?


当前回答

知道枚举就像其他具有常量字段和私有构造函数的类一样是有用的。

例如,

public enum Weekday
{
  MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
} 

编译器按如下方式编译它;

class Weekday extends Enum
{
  public static final Weekday MONDAY  = new Weekday( "MONDAY",   0 );
  public static final Weekday TUESDAY = new Weekday( "TUESDAY ", 1 );
  public static final Weekday WEDNESDAY= new Weekday( "WEDNESDAY", 2 );
  public static final Weekday THURSDAY= new Weekday( "THURSDAY", 3 );
  public static final Weekday FRIDAY= new Weekday( "FRIDAY", 4 );
  public static final Weekday SATURDAY= new Weekday( "SATURDAY", 5 );
  public static final Weekday SUNDAY= new Weekday( "SUNDAY", 6 );

  private Weekday( String s, int i )
  {
    super( s, i );
  }

  // other methods...
}

其他回答

从Java文档-

您应该在任何时候使用枚举类型 需要表示一个固定的集合 常量。包括自然enum 比如我们太阳系中的行星 你知道的系统和数据集 编译时所有可能的值 时间——例如,a上的选项 菜单、命令行标志等等。

一个常见的例子是用枚举类型替换一个类,用一组私有静态final int常量(常量数量合理)。基本上,如果你认为你在编译时知道“something”的所有可能值,你可以将其表示为枚举类型。比起带有常量的类,枚举提供了可读性和灵活性。

枚举类型几乎没有其他优点。它们总是特定枚举类的一个实例(因此出现了使用枚举作为单例的概念)。另一个优点是可以在switch-case语句中使用枚举作为类型。你也可以在枚举上使用toString()将它们打印为可读的字符串。

让我恍然大悟的是:Enum有一个私有构造函数,只能通过公共枚举来访问:

enum RGB {
    RED("Red"), GREEN("Green"), BLUE("Blue");

    public static final String PREFIX = "color ";

    public String getRGBString() {
        return PREFIX + color;
    }

    String color;

    RGB(String color) {
        this.color = color;
    }
}

public class HelloWorld {
    public static void main(String[] args) {
        String c = RGB.RED.getRGBString();
        System.out.print("Hello " + c);
    }
}

到目前为止,我从未需要使用枚举。自从它们在1.5或tiger版本中被引入以来,我就一直在阅读有关它们的文章。他们从未真正为我解决过一个“问题”。对于那些使用它的人(我看到他们中的很多人这样做),我确信它肯定有某种目的。只有我的2英镑。

枚举是什么

enum是为枚举定义的关键字,是一种新的数据类型。应该广泛使用类型安全枚举。特别是,它们是较老api中用来表示相关项集的简单String或int常量的健壮替代。

为什么使用enum

enum是java.lang.Enum的隐式final子类 如果枚举是类的成员,则它是隐式静态的 New永远不能用于枚举,即使是在枚举类型本身中 name和valueOf简单地使用枚举常量的文本,而toString可以被覆盖以提供任何内容,如果需要的话 对于枚举常量,equals和==等于同一个东西,并且可以互换使用 枚举常量是隐式的公共静态final

Note

枚举不能扩展任何类。 enum不能是超类。 枚举常量的出现顺序被称为它们的“自然顺序”,并定义了其他项使用的顺序:compareTo,值的迭代顺序,EnumSet, EnumSet.range。 枚举可以有构造函数、静态和实例块、变量和方法,但不能有抽象方法。

当一个变量(特别是一个方法参数)只能从一组可能的值中选取一个时,您应该始终使用枚举。例如类型常量(合约状态:“永久”,“临时”,“学徒”)或标志(“立即执行”,“延迟执行”)。

如果使用枚举而不是整数(或字符串代码),则增加了编译时检查,避免了传入无效常量的错误,并且记录了哪些值是可以合法使用的。

顺便说一句,过度使用枚举可能意味着你的方法做了太多的事情(通常有几个单独的方法会更好,而不是一个方法有几个标记来修改它所做的事情),但如果你必须使用标记或类型代码,枚举是最好的选择。

举个例子,哪个更好?

/** Counts number of foobangs.
 * @param type Type of foobangs to count. Can be 1=green foobangs,
 * 2=wrinkled foobangs, 3=sweet foobangs, 0=all types.
 * @return number of foobangs of type
 */
public int countFoobangs(int type)

/** Types of foobangs. */
public enum FB_TYPE {
 GREEN, WRINKLED, SWEET, 
 /** special type for all types combined */
 ALL;
}

/** Counts number of foobangs.
 * @param type Type of foobangs to count
 * @return number of foobangs of type
 */
public int countFoobangs(FB_TYPE type)

方法调用如下:

int sweetFoobangCount = countFoobangs(3);

然后就变成:

int sweetFoobangCount = countFoobangs(FB_TYPE.SWEET);

在第二个例子中,很明显哪些类型是允许的,文档和实现不能不同步,编译器可以强制执行这一点。 另外,无效调用

int sweetFoobangCount = countFoobangs(99);

已经不可能了。