枚举帮助/建议 - java

时间:2012-03-16 18:09:08

标签: java enums

在以下情况下是否可以使用枚举:

假设您有一定数量的预定义“读取类型”。例如读类型可以是:诊断,KWH,MaxDemand,OnPeak等,并为每个这些读类型,有一个“TIMTagNumber”,这是essientally用于检索每个预定义的读类型的协议。

例如,TIMTagNumber 1100将检索读取类型Diagnostic TIMTagNumber 1300将检索读取类型KWH。 问题是预定义的读取类型可以由多个TIMTagNumber检索有时

我想创建一个枚举ReadType,它将定义每个读取类型以及可用于检索该读取的所有TIMTagNumbers。 你能用这种方式使用枚举吗?

public enum ReadType{
    KWH(1300)
    Diagnostic(1100)
    ReadType3(1400, 1401) // This read can be retrieved by both 1400 and 1401
}

如果枚举不是可行的方法,是否有优雅或有效的方法来定义这些读取类型?所有这些的总体期望结果是正在识别基于TIMTagNumbers的读取类型。

即。鉴于1400 OR 1401,您会知道它是'ReadType3'。

5 个答案:

答案 0 :(得分:4)

你能做到吗?是。是否正确的决定将取决于您是否要将这些TIMTagNumbers耦合到读取类型。如果没有,简单的Map<Integer, ReadType>可能就足够了。

以下是你如何做到的:

public static enum MyEnum {
    KWH(1300), 
    Diagnostic(1100),
    ReadType3(1400, 1401);

    private Set<Integer> timTagNumbers;

    MyEnum(Integer... timTagNumbers) {
        this.timTagNumbers = new HashSet<Integer>(Arrays.asList(timTagNumbers));
        //add check to make sure that values are unique across all instances
    }

    public static MyEnum forTIMTagNumber(int num) {
        for ( MyEnum readType : values() ) {
             if ( readType.timTagNumbers.contains(num) ) {
                 return readType;
             }
        }
        throw new NoSuchElementException("No ReadType matching TIMTagNumber " + num);
    }
}

//...
int timTagNumber = 1400;
ReadType readType = ReadType.forTIMTagNumber(timTagNumber);

正如我上面所说,当数据和枚举类型已经内在耦合时,这种风格很有效。当枚举类型与映射值分离时(例如,这些值用于序列化枚举的多种方式之一)或者值是特定于配置的还是动态的(例如,如果它们是价格的话),那就不好了一个物品)。在这些情况下,通常最好将此映射外部化为EnumMapMap

答案 1 :(得分:3)

public enum ReadType {
    KWH(1300),
    Diagnostic(1100),
    ReadType3(1400, 1401);

    private int[] timTagNumbers;

    private ReadType(int ... numbers) {
        this.timTagNumbers = numbers;
    }

    public int[] getTimTagNumbers() {
        return timTagNumbers;
    }

    public static ReadType forTimTagNumber(int n) {
        for (ReadType type : values()) {
            if (Arrays.binarySearch(type.timTagNumbers, n) != -1) {
                return type;
            }
        }

        throw new NoSucheElementException();  // if not found
    }

这样你可以做到

int[] timTagNumbers = ReadType.Diagnostic.getTimTagNumbers();  // [ 1100 ]

ReadType type3 = ReadType.forTimTagNumber(1401);  // ReadType.ReadType3

答案 2 :(得分:0)

您确实可以以这种方式使用枚举,但您的示例缺少私有字段和构造函数。

类似的东西:

public enum Bla{
    CASE1(100),CASE2(200);

    private int amount;

    private Bla(int amount) {
        this.amount = amount;
    }

    public Bla getByValue(int value){
        switch (value) {
            case 100: return CASE1;
            case 200: return CASE2;
        }
        return null;
    }

}

我已经包含了一个“反向查找”方法,该方法返回给定值的枚举。

主要的优点是你可以使用“Bla”而不是int来使用其余代码,这将保证操作的类型安全性,基本上,它将无法将无效的int值作为方法参数传递(并且你也可以在枚举上使用switch语句,这在某些使用场景中非常棒)。

编辑:我注意到在发布之后你需要多一个int来指定枚举,但同样的逻辑适用,当然还有方法的适当变化。

答案 3 :(得分:0)

您可以执行以下操作,当您在声明枚举变量的括号中提供值时,它会调用枚举的构造函数。您需要在枚举本身中创建一个不同的方法,以从整数值中获取枚举类型。见下文。

public enum ReadType {
        KWH(), DIAGNOSTIC(), READTYPE3();

        public ReadType getReadType(int num) {
            ReadType toReturn = KWH;
            switch (num) {
            case 1300:
                toReturn = KWH;
                break;
            case 1100:
                toReturn = DIAGNOSTIC;
                break;
            case 1400:
                toReturn = READTYPE3;
                break;
            case 1401:
                toReturn = READTYPE3;
                break;
            }
            return toReturn;

        }

答案 4 :(得分:0)

如果您可以施加一些限制,例如不超过2个标签可以与读取类型相关联,并且每个标签不大于2 ^ 15,那么您可以将这两个数字存储为1个整数。有关详细信息,请参阅this S / O帖子。