【问题标题】:Is it possible to assign numeric value to an enum in Java?是否可以将数值分配给 Java 中的枚举?
【发布时间】:2023-04-07 15:49:02
【问题描述】:

在 Java 中这样的事情是可能的吗?可以为 Java 中的枚举元素分配自定义数值吗?

public enum EXIT_CODE {
    A=104, B=203;
}

【问题讨论】:

  • 不像你写的那样直接,即枚举值等于一个数字,但如 Ben S 的链接所示,是间接的。
  • @Benoit 我不认为这是一个骗局:一个是关于设置第一个值并从那里递增,这是关于设置所有值。但绝对相关。

标签: java enums


【解决方案1】:

我意识到这是一个较老的问题,但它首先出现在谷歌搜索中,在提供的优秀答案中,我没有看到任何全面的内容,所以我做了更多的挖掘,最后我写了一个enum 类不仅允许我为枚举常量分配多个自定义值,我什至添加了一个方法,允许我在代码执行期间动态为它们分配值。

这个枚举类用于我在 Raspberry Pi 上运行的“服务器”程序。该程序接收来自客户端的命令,然后执行终端命令,对固定在我的 3D 打印机上的网络摄像头进行调整。

使用 Pi 上的 Linux 程序“v4l2-ctl”,您可以提取给定附加网络摄像头的所有可能调整命令,它还提供设置数据类型、最小值和最大值、值步数一个给定的值范围等,所以我把所有这些都放在一个枚举中并创建了一个枚举接口,它可以轻松设置和获取每个命令的值以及获取实际终端命令的简单方法执行(使用 Process 和 Runtime 类)以调整设置。

这是一个相当大的课程,对此我深表歉意,但对我来说,当我看到它在完整的上下文中工作时,学习一些东西总是更容易,所以我决定不缩小它。然而,尽管它很大,但它绝对是简单的,而且只需最少的努力就能清楚地看到课堂上发生的事情。

package constants;

import java.util.HashMap;
import java.util.Map;

public enum PICam {
    BRIGHTNESS                  ("brightness",                  0,      "int",      0,      100,    1,  50),
    CONTRAST                    ("contrast",                    1,      "int",      100,    100,    1,  0),
    SATURATION                  ("saturation",                  2,      "int",      100,    100,    1,  0),
    RED_BALANCE                 ("red_balance",                 3,      "intmenu",  1,      7999,   1,  1000),
    BLUE_BALANCE                ("blue_balance",                4,      "int",      1,      7999,   1,  1000),
    HORIZONTAL_FLIP             ("horizontal_flip",             5,      "bool",     0,      1,      1,  0),
    VERTICAL_FLIP               ("vertical_flip",               6,      "bool",     0,      1,      1,  0),
    POWER_LINE_FREQUENCY        ("power_line_frequency",        7,      "menu",     0,      3,      1,  1),
    SHARPNESS                   ("sharpness",                   8,      "int",      100,    100,    1,  0),
    COLOR_EFFECTS               ("color_effects",               9,      "menu",     0,      15,     1,  0),
    ROTATE                      ("rotate",                      10,     "int",      0,      360,    90, 0),
    COLOR_EFFECTS_CBCR          ("color_effects_cbcr",          11,     "int",      0,      65535,  1,  32896),
    VIDEO_BITRATE_MODE          ("video_bitrate_mode",          12,     "menu",     0,      1,      1,  0),
    VIDEO_BITRATE               ("video_bitrate",               13,     "int",      25000,  25000000,   25000,  10000000),
    REPEAT_SEQUENCE_HEADER      ("repeat_sequence_header",      14,     "bool",     0,      1,      1,  0),
    H264_I_FRAME_PERIOD         ("h_264_i_frame_period",        15,     "int",      0,      2147483647,1,   60),
    H264_LEVEL                  ("h_264_level",                 16,     "menu",     0,      11,     1,  11),
    H264_PROFILE                ("h_264_profile",               17,     "menu",     0,      4,      1,  4),
    AUTO_EXPOSURE               ("auto_exposure",               18,     "menu",     0,      3,      1,  0),
    EXPOSURE_TIME_ABSOLUTE      ("exposure_time_absolute",      19,     "int",      1,      10000,  1,  1000),
    EXPOSURE_DYNAMIC_FRAMERATE  ("exposure_dynamic_framerate",  20,     "bool",     0,      1,      1,  0),
    AUTO_EXPOSURE_BIAS          ("auto_exposure_bias",          21,     "intmenu",  0,      24,     1,  12),
    WHITE_BALANCE_AUTO_PRESET   ("white_balance_auto_preset",   22,     "menu",     0,      9,      1,  1),
    IMAGE_STABILIZATION         ("image_stabilization",         23,     "bool",     0,      1,      1,  0),
    ISO_SENSITIVITY             ("iso_sensitivity",             24,     "intmenu",  0,      4,      1,  0),
    ISO_SENSITIVITY_AUTO        ("iso_sensitivity_auto",        25,     "menu",     0,      1,      1,  1),
    EXPOSURE_METERING_MODE      ("exposure_metering_mode",      26,     "menu",     0,      2,      1,  0),
    SCENE_MODE                  ("scene_mode",                  27,     "menu",     0,      13,     1,  0),
    COMPRESSION_QUALITY         ("compression_quality",         28,     "int",      1,      100,    1,  30);


    private static final Map<String, PICam>    LABEL_MAP       = new HashMap<>();
    private static final Map<Integer, PICam>   INDEX_MAP       = new HashMap<>();
    private static final Map<String, PICam>    TYPE_MAP        = new HashMap<>();
    private static final Map<Integer, PICam>   MIN_MAP         = new HashMap<>();
    private static final Map<Integer, PICam>   MAX_MAP         = new HashMap<>();
    private static final Map<Integer, PICam>   STEP_MAP        = new HashMap<>();
    private static final Map<Integer, PICam>   DEFAULT_MAP     = new HashMap<>();
    private static final Map<Integer, Integer> THIS_VALUE_MAP  = new HashMap<>();

    private static final String                baseCommandLine = "/usr/bin/v4l2-ctl -d /dev/video0 --set-ctrl=";

    static {
        for (PICam e: values()) {
            LABEL_MAP.put(e.label, e);
            INDEX_MAP.put(e.index, e);
            TYPE_MAP.put(e.type, e);
            MIN_MAP.put(e.min, e);
            MAX_MAP.put(e.max, e);
            STEP_MAP.put(e.step, e);
            DEFAULT_MAP.put(e.defaultValue, e);
        }
    }

    public final String label;
    public final int index;
    public final String type;
    public final int min;
    public final int max;
    public final int step;
    public final int defaultValue;

    private PICam(String label, int index, String type, int min, int max, int step, int defaultValue) {
        this.label = label;
        this.index = index;
        this.type = type;
        this.min = min;
        this.max = max;
        this.step = step;
        this.defaultValue = defaultValue;
    }

    public static void setValue(Integer index, Integer value) {
        if (THIS_VALUE_MAP.containsKey(index)) THIS_VALUE_MAP.replace(index, value);
        else THIS_VALUE_MAP.put(index, value);
    }

    public Integer getValue (Integer index) {
        return THIS_VALUE_MAP.getOrDefault(index, null);
    }

    public static PICam getLabel(String label) {
        return LABEL_MAP.get(label);
    }

    public static PICam getType(String type) {
        return TYPE_MAP.get(type);
    }

    public static PICam getMin(int min) {
        return MIN_MAP.get(min);
    }

    public static PICam getMax(int max) {
        return MAX_MAP.get(max);
    }

    public static PICam getStep(int step) {
        return STEP_MAP.get(step);
    }

    public static PICam getDefault(int defaultValue) {
        return DEFAULT_MAP.get(defaultValue);
    }

    public static String getCommandFor(int index, int newValue) {
        PICam picam = INDEX_MAP.get(index);
        String commandValue = "";
        if ("bool".equals(picam.type)) {
            commandValue = (newValue == 0) ? "false" : "true";
        }
        else {
            commandValue = String.valueOf(newValue);
        }
        return baseCommandLine + INDEX_MAP.get(index).label + "=" + commandValue;
    }

    public static String getCommandFor(PICam picam, Integer newValue) {
        String commandValue = "";
        if ("bool".equals(picam.type)) {
            commandValue = (newValue == 0) ? "false" : "true";
        }
        else {
            commandValue = String.valueOf(newValue);
        }
        return baseCommandLine + INDEX_MAP.get(picam.index).label + "=" + commandValue;
    }

    public static String getCommandFor(PICam piCam) {
        int    newValue     = piCam.defaultValue;
        String commandValue = "";
        if ("bool".equals(piCam.type)) {
            commandValue = (newValue == 0) ? "false" : "true";
        }
        else {
            commandValue = String.valueOf(newValue);
        }
        return baseCommandLine + piCam.label + "=" + commandValue;
    }

    public static String getCommandFor(Integer index) {
        PICam piCam = INDEX_MAP.get(index);
        int    newValue     = piCam.defaultValue;
        String commandValue = "";
        if ("bool".equals(piCam.type)) {
            commandValue = (newValue == 0) ? "false" : "true";
        }
        else {
            commandValue = String.valueOf(newValue);
        }
        return baseCommandLine + piCam.label + "=" + commandValue;
    }
}

以下是可以与该类进行交互的一些方式:

这段代码:

public static void test() {
    PICam.setValue(0,127); //Set brightness to 125
    PICam.setValue(PICam.SHARPNESS,143); //Set sharpness to 125
    String command1 = PICam.getSetCommandStringFor(PICam.BRIGHTNESS); //Get command line string to include the brightness value that we previously set referencing it by enum constant.
    String command2 = PICam.getSetCommandStringFor(0); //Get command line string to include the brightness value that we previously set referencing it by index number.
    String command3 = PICam.getDefaultCamString(PICam.BRIGHTNESS); //Get command line string with the default value
    String command4 = PICam.getSetCommandStringFor(PICam.SHARPNESS); //Get command line string with the sharpness value that we previously set.
    String command5 = PICam.getDefaultCamString(PICam.SHARPNESS); //Get command line string with the default sharpness value.
    System.out.println(command1);
    System.out.println(command2);
    System.out.println(command3);
    System.out.println(command4);
    System.out.println(command5);
}

产生这些结果:

/usr/bin/v4l2-ctl -d /dev/video0 --set-ctrl=brightness=127
/usr/bin/v4l2-ctl -d /dev/video0 --set-ctrl=brightness=127
/usr/bin/v4l2-ctl -d /dev/video0 --set-ctrl=brightness=50
/usr/bin/v4l2-ctl -d /dev/video0 --set-ctrl=sharpness=143
/usr/bin/v4l2-ctl -d /dev/video0 --set-ctrl=sharpness=0

【讨论】:

    【解决方案2】:

    如果您正在寻找一种对类中的常量进行分组的方法,您可以使用静态内部类:

    public class OuterClass {
        public void exit(boolean isTrue){
            if(isTrue){
                System.exit(ExitCode.A);
            }else{
                System.exit(ExitCode.B);
            }
        }
        public static class ExitCode{
            public static final int A = 203;
            public static final int B = 204;
        }   
    }
    

    【讨论】:

      【解决方案3】:

      扩展 Bhesh Gurung 的赋值答案,您可以添加显式方法来设置值

         public ExitCode setValue( int value){
            //  A(104), B(203);
            switch(value){
              case 104: return ExitCode.A;
              case 203: return ExitCode.B;
              default:
                         return ExitCode.Unknown //Keep an default or error enum handy
            }
         }
      

      来自调用应用程序

      int i = 104; 
      ExitCode serverExitCode = ExitCode.setValue(i);
      

      //从现在开始你的枚举是有效的

      [无法评论他的回答,因此单独发布]

      【讨论】:

        【解决方案4】:

        假设 EXIT_CODE 指的是System . exit ( exit_code ) 那么你可以这样做

        enum ExitCode
        {
              NORMAL_SHUTDOWN ( 0 ) , EMERGENCY_SHUTDOWN ( 10 ) , OUT_OF_MEMORY ( 20 ) , WHATEVER ( 30 ) ;
        
              private int value ;
        
              ExitCode ( int value )
              {
                   this . value = value ;
              }
        
              public void exit ( )
              {
                    System . exit ( value ) ;
              }
        }
        

        然后您可以将以下内容放在代码中的适当位置

        ExitCode . NORMAL_SHUTDOWN . exit ( ) '

        【讨论】:

          【解决方案5】:
          public enum EXIT_CODE {
              A(104), B(203);
          
              private int numVal;
          
              EXIT_CODE(int numVal) {
                  this.numVal = numVal;
              }
          
              public int getNumVal() {
                  return numVal;
              }
          }
          

          【讨论】:

          • 您不能在代码中使用枚举构造函数。 EXIT_CODE.AEXIT_CODE.B 是唯一存在的实例。
          • @IgorGanapolsky 特别是,枚举的构造函数不能公开:stackoverflow.com/questions/3664077/…
          • 这仍然适用于 gson 并从 json 转换。
          • 您也可以声明变量“public final int numVal”并直接作为 EXIT_CODE.A.numVal 访问它(我更喜欢名称“value”),而不需要访问器方法。由于是final,只能在构造函数中设置。 IMO 它导致代码稍微干净一些,但我想这主要是一个偏好问题。使用 final 变量可以为您节省一个方法定义。
          【解决方案6】:

          Yes,然后是文档中的一些示例:

          public enum Planet {
              MERCURY (3.303e+23, 2.4397e6),
              VENUS   (4.869e+24, 6.0518e6),
              EARTH   (5.976e+24, 6.37814e6),
              MARS    (6.421e+23, 3.3972e6),
              JUPITER (1.9e+27,   7.1492e7),
              SATURN  (5.688e+26, 6.0268e7),
              URANUS  (8.686e+25, 2.5559e7),
              NEPTUNE (1.024e+26, 2.4746e7);
          
              // in kilograms
              private final double mass;
              // in meters
              private final double radius;
              Planet(double mass, double radius) {
                  this.mass = mass;
                  this.radius = radius;
              }
              private double mass() { return mass; }
              private double radius() { return radius; }
          
              // universal gravitational 
              // constant  (m3 kg-1 s-2)
              public static final double G = 6.67300E-11;
          
              double surfaceGravity() {
                  return G * mass / (radius * radius);
              }
              double surfaceWeight(double otherMass) {
                  return otherMass * surfaceGravity();
              }
              public static void main(String[] args) {
                  if (args.length != 1) {
                      System.err.println("Usage: java Planet <earth_weight>");
                      System.exit(-1);
                  }
                  double earthWeight = Double.parseDouble(args[0]);
                  double mass = earthWeight/EARTH.surfaceGravity();
                  for (Planet p : Planet.values())
                     System.out.printf("Your weight on %s is %f%n",
                                       p, p.surfaceWeight(mass));
              }
          }
          

          【讨论】:

          • 为什么你的 public static void main(String[] args) 在枚举本身里面??
          • @IgorGanapolsky 我猜为了让示例独立!
          • @IgorGanapolsky:因为在官方文档中就是这样(点击Yes-link)
          • @user1587329 有趣,我想这只是为了测试目的。我看不到在生产版本代码中使用它的方法...
          猜你喜欢
          • 1970-01-01
          • 2022-01-20
          • 1970-01-01
          • 1970-01-01
          • 2021-10-21
          • 1970-01-01
          • 2014-08-04
          • 2011-02-08
          • 2013-01-08
          相关资源
          最近更新 更多