使用Java Enums模拟C ++枚举整数

时间:2010-10-05 22:17:19

标签: java enums

我正在尝试将一些C ++代码翻译成Java。我正在寻找在Java中模拟这种类型的C ++范例的最佳方法 - 我认为枚举可能是答案,但我对任何事情持开放态度

C ++代码:

typedef UInt32 Type;
enum { UNKNOWN, QUIT, SYSTEM, TIMER, LAST }
...
Type newType = UNKNOWN;
Type nextType = LAST + 1;
...
// "Register" the new type
newType = nextType;
nextType++;
...
switch (newType) {
   case UNKNOWN:
   case QUIT:
   ...
   case LAST:
          // Ignore unset or predefined types
   default:
          // Some type other than the predefined.  Do something special

基本上我正在寻找一种“扩展”Java枚举值的方法。

enum Type { UNKNOWN, QUIT, SYSTEM, TIMER, LAST } 

不会退出它。

我喜欢为强类型创建一个新对象的想法。

同样,我正在寻找在这里使用的最佳模式。我可以轻松地通过一些公共静态最终int UNKNOWN等来漂浮

2 个答案:

答案 0 :(得分:3)

Java枚举的一个优点是,它们本质上就像所有其他对象一样。特别是,您可以在常量上使用方法,并使您的枚举实现接口:

interface Useful {
    void doStuff();
}

enum Foo implements Useful {
    DEFAULT { 
        public void doStuff() {
            ...
        }
    },
    MAGIC {
        public void doStuff() { 
            ...
        }
    }
}

因此,您的方法不是接受枚举类型的参数,而是接受接口的任何实现,特别是通过让枚举常量实现任何必要的实现来提供默认的东西。

他们也可以有成员:

enum Explicit {
    FIRST(0), SECOND(1), THIRD(2);

    private final int value;

    private Explicit(int v) {
        this.value = v;
    }
}

注意,常量有一个内部数值(反映其对等体中常量的位置),可以使用ordinal方法访问:

assert Explicit.FIRST.ordinal() == 0;

但依靠这一点有点危险。如果你打算(比如说)在数据库中保存枚举常量,那么以下更改将破坏代码:

enum Explicit {
    FIRST(0), NEWELT(-1), SECOND(1), THIRD(2);

    private final int value;

    private Explicit(int v) {
        this.value = v;
    }
}

使用序数值时。因此,序列化机制在序列化枚举值时使用常量名称而不是其位置。

所以:

Type.X + 1

将是

Enum.values()[Enum.X.ordinal() + 1]

并且交换机可以使用枚举本身实现的接口建模(您可以在Java中使用switch语句中的枚举,但通常,使枚举实现必要的代码会产生更易维护的代码)

答案 1 :(得分:2)

如果Type的每个值只是一个int,那么我可能会在类中找到一堆静态最终的int。

只是为了记录,这样的东西或多或少类型安全。如果不了解更多问题,我无法确定复杂性是否合理。

public class abstract Type
{ 
   public static final Type UNKNOWN   = registerStd("UNKNOWN");
   ...
   public static final Type TIMER     = registerStd("TIMER");

   // use this to keep track of all the types
   private static final List<Type> REGISTERED = ...

   //This will do your switch statement for you, implemented by 
   // anonymous subclasses
   public abstract void dispatch(Type onMe);

   // here's how you make the standard ones
   private static Type registerStd(String name)
   {
       Type heresOne = new Type(name) 
       { 
          // note, it's a no-op
          public void dispatch(DoStuffer algorithm) {} 
       };
       REGISTERED.add(heresOne);
       return heresOne;
   }

   //here's how you make the non-standard ones
   public static Type registerNew(String name)
   {
       Type heresOne = new Type(name) 
       {
          public void dispatch(DoStuffer algorithm) {algorithm.execute(this)} 
       };
       REGISTERED.add(heresOne);
       return heresOne;
   }

}

public interface DoStuffer 
{
   public void execute(Type onMe);
}

//Then your code becomes
Type newType = Type.registerNew("NewType");

newType.dispatch
(
     new DoStuffer() 
     {
        public void algorithm(Type forMe) { ... } 
     }
);

也许这有点深奥。但它确实允许在调用者站点“易于调度”和在某种意义上的可扩展枚举。