将整数值转换为匹配的Java Enum

时间:2011-03-13 22:08:25

标签: java

我有一个这样的枚举:

public enum PcapLinkType {
  DLT_NULL(0)
  DLT_EN10MB(1)
  DLT_EN3MB(2),
  DLT_AX25(3),
  /*snip, 200 more enums, not always consecutive.*/
  DLT_UNKNOWN(-1);
    private final int value;   

    PcapLinkType(int value) {
        this.value= value;
    }
}

现在我从外部输入获取一个int并想要匹配的输入 - 如果某个值不存在则抛出异常是正常的,但在这种情况下我最好是DLT_UNKNOWN

int val = in.readInt();
PcapLinkType type = ???; /*convert val to a PcapLinkType */

12 个答案:

答案 0 :(得分:96)

您需要手动执行此操作,方法是在将整数映射到枚举的类中添加静态映射,例如

private static final Map<Integer, PcapLinkType> intToTypeMap = new HashMap<Integer, PcapLinkType>();
static {
    for (PcapLinkType type : PcapLinkType.values()) {
        intToTypeMap.put(type.value, type);
    }
}

public static PcapLinkType fromInt(int i) {
    PcapLinkType type = intToTypeMap.get(Integer.valueOf(i));
    if (type == null) 
        return PcapLinkType.DLT_UNKNOWN;
    return type;
}

答案 1 :(得分:30)

有一个静态方法values() 记录,但不是你期望的那样:http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

enum MyEnum {
    FIRST, SECOND, THIRD;
    private static MyEnum[] allValues = values();
    public static MyEnum fromOrdinal(int n) {return allValues[n];}
}

原则上,您只能使用values()[i],但有传言称values()每次调用时都会创建数组的副本。

答案 2 :(得分:14)

您必须创建一个新的静态方法,迭代PcapLinkType.values()并进行比较:

public static PcapLinkType forCode(int code) {
    for (PcapLinkType typе : PcapLinkType.values()) {
        if (type.getValue() == code) {
            return type;
        }
    }
    return null;
 }

如果很少被调用那就没问题。如果经常调用它,请查看其他人建议的Map优化。

答案 3 :(得分:9)

你可以做这样的事情来自动将它们全部注册到一个集合中,然后可以轻松地将整数转换为相应的枚举。 (顺便说一下,在枚举构造函数is not allowed中将它们添加到地图中。即使在使用Java多年后学习新东西也很好。)

public enum PcapLinkType {
    DLT_NULL(0),
    DLT_EN10MB(1),
    DLT_EN3MB(2),
    DLT_AX25(3),
    /*snip, 200 more enums, not always consecutive.*/
    DLT_UNKNOWN(-1);

    private static final Map<Integer, PcapLinkType> typesByValue = new HashMap<Integer, PcapLinkType>();

    static {
        for (PcapLinkType type : PcapLinkType.values()) {
            typesByValue.put(type.value, type);
        }
    }

    private final int value;

    private PcapLinkType(int value) {
        this.value = value;
    }

    public static PcapLinkType forValue(int value) {
        return typesByValue.get(value);
    }
}

答案 4 :(得分:9)

如果你有这样的枚举

public enum PcapLinkType {
  DLT_NULL(0)
  DLT_EN10MB(1)
  DLT_EN3MB(2),
  DLT_AX25(3),
  DLT_UNKNOWN(-1);

    private final int value;   

    PcapLinkType(int value) {
        this.value= value;
    }
}

然后你可以像

一样使用它
PcapLinkType type = PcapLinkType.values()[1]; /*convert val to a PcapLinkType */

答案 5 :(得分:4)

正如@MeBigFatGuy所说,除了你可以让static {...}块使用values()集合上的循环:

static {
    for (PcapLinkType type : PcapLinkType.values()) {
        intToTypeMap.put(type.getValue(), type);
    }
}

答案 6 :(得分:4)

我知道这个问题已经有几年了,但是正如Java 8所带来的那样,同时带给我们Optional,我想我会提供一个使用它的解决方案(和StreamCollectors):

Optional

nullnull类似:它代表没有(有效)值的情况。但它是DLT_UNKNOWN或类型null等默认值的更安全的替代方法,因为您可能忘记检查DLT_UNKNOWNPcapLinkType个案例。它们都是有效的Optional<PcapLinkType>值!相反,您无法将PcapLinkType值分配给Optional类型的变量。 DLT_UNKNOWN会让您先检查有效值。

当然,如果您希望保留Optional以实现向后兼容性或其他原因,即使在这种情况下,仍然可以使用orElse(),使用public enum PcapLinkType { DLT_NULL(0), DLT_EN3MB(2), DLT_AX25(3), /*snip, 200 more enums, not always consecutive.*/ DLT_UNKNOWN(-1); private final int value; private PcapLinkType(int value) { this.value = value; } private static final Map<Integer, PcapLinkType> map; static { map = Arrays.stream(values()) .collect(Collectors.toMap(e -> e.value, e -> e)); } public static PcapLinkType fromInt(int value) { return Optional.ofNullable(map.get(value)).orElse(DLT_UNKNOWN); } } 将其指定为默认值值:

public void dice(){
    int whichOne=(int)(Math.random()*6+1);
    if(whichOne==1){jLabel12.setIcon(new ImageIcon(getClass().getResource("/spanish/dice1.png")));}
    else if(whichOne==2){jLabel12.setIcon(new ImageIcon(getClass().getResource("/spanish/dice2.png")));}
    else if(whichOne==3){jLabel12.setIcon(new ImageIcon(getClass().getResource("/spanish/dice3.png")));}
    else if(whichOne==4){jLabel12.setIcon(new ImageIcon(getClass().getResource("/spanish/dice4.png")));}
    else if(whichOne==5){jLabel12.setIcon(new ImageIcon(getClass().getResource("/spanish/dice5.png")));}
    else if(whichOne==6){jLabel12.setIcon(new ImageIcon(getClass().getResource("/spanish/dice6.png")));}
}

答案 7 :(得分:3)

您可以在枚举中添加静态方法,该方法接受int作为参数并返回PcapLinkType

public static PcapLinkType of(int linkType) {

    switch (linkType) {
        case -1: return DLT_UNKNOWN
        case 0: return DLT_NULL;

        //ETC....

        default: return null;

    }
}

答案 8 :(得分:3)

这就是我使用的:

public enum Quality {ENOUGH,BETTER,BEST;
                     private static final int amount = EnumSet.allOf(Quality.class).size();
                     private static Quality[] val = new Quality[amount];
                     static{ for(Quality q:EnumSet.allOf(Quality.class)){ val[q.ordinal()]=q; } }
                     public static Quality fromInt(int i) { return val[i]; }
                     public Quality next() { return fromInt((ordinal()+1)%amount); }
                    }

答案 9 :(得分:1)

static final PcapLinkType[] values  = { DLT_NULL, DLT_EN10MB, DLT_EN3MB, null ...}    

...

public static PcapLinkType  getPcapLinkTypeForInt(int num){    
    try{    
       return values[int];    
    }catch(ArrayIndexOutOfBoundsException e){    
       return DLT_UKNOWN;    
    }    
}    

答案 10 :(得分:0)

没有办法优雅地处理基于整数的枚举类型。您可能会考虑使用基于字符串的枚举而不是解决方案。一直不是首选方法,但它仍然存在。

public enum Port {
  /**
   * The default port for the push server.
   */
  DEFAULT("443"),

  /**
   * The alternative port that can be used to bypass firewall checks
   * made to the default <i>HTTPS</i> port.
   */
  ALTERNATIVE("2197");

  private final String portString;

  Port(final String portString) {
    this.portString = portString;
  }

  /**
   * Returns the port for given {@link Port} enumeration value.
   * @return The port of the push server host.
   */
  public Integer toInteger() {
    return Integer.parseInt(portString);
  }
}

答案 11 :(得分:0)

这可能不是一个很好的解决方案,但它对我有用:

public enum Type {
        WATER, FIRE, GRASS;

        public static Type getType(int value){
            if(value==WATER.ordinal()){
                return WATER;
            }else if(value==FIRE.ordinal()){
                return FIRE;
            }else if(value==GRASS.ordinal()){
                return GRASS;
            }else {
                return null;
            }
        }
    }