【问题标题】:Access the .values() and .ordinal() method of arbitrary enum?访问任意枚举的 .values() 和 .ordinal() 方法?
【发布时间】:2013-04-25 07:05:56
【问题描述】:

我想要一个模拟 EnumMap 的类,但存储 int 值而不是某种对象。现在显然你可以制作一个映射到整数的 EnumMap,但如果可以的话,我想避免很多自动装箱。

所以我想要这样的课程:

public class EnumIntAttributeMap
{
    enum Attribute
    {
        Height, Weight;
    }

    private final int[] values;

    public EnumIntAttributeMap()
    {
        this.values = new int[Attribute.values().length];
    }

    public int getValue(Attribute a)
    {
        return this.values[a.ordinal()];
    }

    public void setValue(Attribute a, int value)
    {
        this.values[a.ordinal()] = value;
    }
}

除了我想制作一个对所有枚举通用的版本。现在,由于 .values() 和 .ordinal() 方法是由编译器隐式添加的,因此访问它们的唯一方法似乎是使用反射,这会消耗我试图通过避免获得的性能提升自动装箱,但也许我缺少一些东西。

有什么想法吗?

编辑:

我认为我最初的问题不清楚。我想要一个接受(作为通用参数)枚举的类,然后可以使用相同的操作。

所以我可以将它与任何类型的枚举一起使用,而无需每次都为每种枚举编写类。如:

enum Attribute { Height, Weight }

enum AbilityScore {Str, Dex, Con, Int, Wis, Cha}

IdealClass<Attribute> attributeVersion;

IdealClass<AbilityScore> abilityScoreVersion;

等等。

【问题讨论】:

  • 如果您的 int 值很小,即在缓存中,这不会有任何区别(顺便说一句,您可以增加缓存的大小)但是,如果您的 int 值很大,它可以珍惜你的一些记忆/垃圾。
  • 我看到您可以使用命令行参数扩展整数缓存。程序从程序内部启动后,有没有办法做到这一点?

标签: java


【解决方案1】:

这是一个解决方案:

public class EnumIntMap<E extends Enum<E>> {

    private final int[] values;

    public EnumIntMap(Class<E> cls)
    {
        this.values = new int[cls.getEnumConstants().length];
    }

    public int getValue(E a)
    {
        return this.values[a.ordinal()];
    }

    public void setValue(E a, int value)
    {
        this.values[a.ordinal()] = value;
    }
}

您还必须使用枚举的类来初始化地图。

enum Attribute { Height, Weight }

enum AbilityScore {Str, Dex, Con, Int, Wis, Cha}

EnumIntMap<Attribute> attributeVersion = new EnumIntMap(Attribute.class);

EnumIntMap<AbilityScore> abilityScoreVersion = new EnumIntMap(AbilityScore.class);

【讨论】:

  • 哦,这就是你的做法。我一直在尝试做 getDeclaringClass() 和其他奇怪的事情,只是用它把我的头撞到墙上。迷人的。马巴你是我今天最喜欢的人。
【解决方案2】:

在遗传上做到这一点的关键是知道枚举的通用界限:

<T extends Enum<T>>

您的课程可以为 any 枚举工作,如下所示:

public class EnumIntAttributeMap<T extends Enum<T>> {
    private final int[] values;
    private final Class<T> clazz;

    public EnumIntAttributeMap(Class<T> clazz) {
        this.clazz = clazz;
        this.values = new int[clazz.getEnumConstants().length];
    }

    public int getValue(T a) {
        return this.values[a.ordinal()];
    }

    public void setValue(T a, int value) {
        this.values[a.ordinal()] = value;
    }
}

请注意,构造函数需要一个类型标记,这是由于 java 的运行时类型擦除而需要的。

【讨论】:

    【解决方案3】:

    所有 java Enum 隐式扩展 java.lang.Enum,所以我认为您正在寻找的是:

    public class EnumIntAttributeMap<E extends java.lang.Enum<E>> {
        // [...]
    }
    

    【讨论】:

    • 但这只是给你一个 E,你不能在构造函数中调用 .values() 来设置数组长度。
    【解决方案4】:

    阅读:Oracle's Doc on Enums

    我认为你可以做一些类似于行星示例的事情:

    public enum YourEnum{
        HEIGHT (0),
        WIDTH  (1);
    
        private final int index;
    
        YourEnum(int index) {
            this.index = index;
        }
        public int index() { return index; }
    }
    

    【讨论】:

      【解决方案5】:

      这是我个人使用的,它在 API 中给了我很好的标准化

      通用接口:

      public interface IValueEnum<T> {       
         T value();
      }
      

      枚举是这样实现的:

      public enum MyEnum implements IValueEnum<Integer> {
         WIDTH(1),
         HEIGHT(2);
      
         private final int value;
         MyEnum(int value) { this.value = value; }
      
         @Override
         public Integer value() {
            return value;
         }
      }
      

      现在您可以通过 MyEnum.WIDTH.value() 等获取最终值。由于它使用泛型,其他枚举可以使用 Longs 或 Strings 或您拥有的任何东西。它允许您在应用程序中拥有一个简单的基于枚举的接口。它还允许您在 Map 等中完全通用。

      编辑:基于新示例

      public class IdealClass<T extends Enum> {
      
        T enumValue;
      
        public IdealClass() {
        }
      
      }
      

      【讨论】:

      • 我已经在使用枚举的序号作为索引,我希望能够为多个具有相同类的枚举做到这一点。
      • @Lokathor 很好地使用了这种方法,您可以在接口中添加一个名为 getIndex() 的方法,然后您可以使用 IValueEnum 作为泛型类型...不是吗?
      • @Ixx 你……可以吗?但这实际上与我想要的相反。而不是一个可调整的映射让您将 Enum 值映射到整数,您最终会得到一堆静态的最终全局变量。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-09
      相关资源
      最近更新 更多