Czy można przypisać wartość liczbową do wyliczenia w Javie?

134

Czy coś takiego jest możliwe w Javie? Czy można przypisać niestandardowe wartości liczbowe do elementów wyliczenia w języku Java?

public enum EXIT_CODE {
    A=104, B=203;
}
James Raitsev
źródło
Nie bezpośrednio, jak napisałeś, tj. Gdzie wartość wyliczenia jest równa liczbie, ale tak, pośrednio, jak pokazano w linku Ben S.
Poduszkowiec pełen węgorzy
@Benoit Nie wydaje mi się, żeby to było oszustwo: chodzi o ustawienie tylko pierwszej wartości i zwiększanie jej wartości, chodzi o ustawienie wszystkich wartości. Ale zdecydowanie powiązane.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Odpowiedzi:

217
public enum EXIT_CODE {
    A(104), B(203);

    private int numVal;

    EXIT_CODE(int numVal) {
        this.numVal = numVal;
    }

    public int getNumVal() {
        return numVal;
    }
}
Bhesh Gurung
źródło
13
W kodzie nie można używać konstruktora wyliczenia. EXIT_CODE.Ai EXIT_CODE.Bsą jedynymi instancjami, które kiedykolwiek będą istnieć.
Bhesh Gurung
2
W szczególności @IgorGanapolsky, konstruktor wyliczenia nie może być publiczny: stackoverflow.com/questions/3664077/ ...
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
czy to nadal będzie działać z gson i konwertowaniem z json.
Zapnologica
4
Możesz również zadeklarować zmienną „public final int numVal” i po prostu uzyskać do niej bezpośredni dostęp jako EXIT_CODE.A.numVal (wolę nazwę „wartość”), bez potrzeby stosowania metody akcesora. Ponieważ jest ostateczny, można go ustawić tylko w konstruktorze. IMO prowadzi to do nieco czystszego kodu, ale przypuszczam, że jest to głównie kwestia preferencji. Użycie ostatniej zmiennej oszczędza jedną definicję metody.
Steve Ferguson
34

Tak , a potem trochę, przykład z dokumentacji:

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));
    }
}
Ben S.
źródło
Dlaczego twój public static void main (String [] args) znajduje się wewnątrz samego wyliczenia?
IgorGanapolsky
3
@IgorGanapolsky Chyba żeby przykład był samowystarczalny!
mat_boy
2
@IgorGanapolsky: ponieważ tak jest w oficjalnych dokumentach (postępuj zgodnie z linkiem Tak )
serv-inc
@ user1587329 Ciekawe, myślę, że to tylko do celów testowych. Nie widzę sposobu, aby użyć tego w kodzie wydania produkcyjnego ...
IgorGanapolsky
12

Zakładając, że EXIT_CODE odnosi się do System . exit(kod_wyjścia), możesz to zrobić

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 ) ;
      }
}

Następnie możesz umieścić następujące elementy w odpowiednich miejscach w kodzie

ExitCode . NORMAL_SHUTDOWN . exit ( ) '

emory
źródło
3

Rozszerzając odpowiedź Bhesha Gurunga na przypisywanie wartości, możesz dodać jawną metodę do ustawiania wartości

   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
      }
   }

Z aplikacji wywołującej

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

// Od teraz masz prawidłowe wyliczenie

[Nie można skomentować jego odpowiedzi, dlatego zamieszczam ją oddzielnie]

Sudhakar
źródło
2

Jeśli szukasz sposobu na grupowanie stałych w klasie, możesz użyć statycznej klasy wewnętrznej:

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;
    }   
}
Rigo Brinkman
źródło
0

Zdaję sobie sprawę, że jest to starsze pytanie, ale pojawia się jako pierwsze w wyszukiwarce Google, a wśród doskonałych odpowiedzi nie znalazłem nic w pełni wyczerpującego, więc poszedłem trochę więcej i skończyło się na napisaniu klasy wyliczeniowej, która nie tylko pozwoliło mi przypisać wiele wartości niestandardowych do stałych wyliczenia, ale nawet dodałem metodę, która pozwala mi przypisywać do nich wartości w locie podczas wykonywania kodu.

Ta klasa wyliczeniowa jest przeznaczona dla programu „serwerowego”, który uruchamiam na Raspberry Pi. Program otrzymuje polecenia od klienta, a następnie wykonuje polecenia terminala, które dostosowują kamerę internetową podłączoną do mojej drukarki 3D.

Używając programu Linux `` v4l2-ctl '' na Pi, możesz wyodrębnić wszystkie możliwe polecenia regulacji dla danej podłączonej kamery internetowej, które również zapewniają ustawienie typu danych, wartości minimalne i maksymalne, liczbę kroków wartości w danej wartości zakres itp., więc wziąłem je wszystkie i umieściłem je w wyliczeniu i utworzyłem interfejs wyliczenia, który ułatwia zarówno ustawianie, jak i pobieranie wartości dla każdego polecenia, a także prostą metodę uzyskiwania rzeczywistego polecenia terminala, które jest wykonywane ( za pomocą klas Process i Runtime) w celu dostosowania ustawienia.

To dość duża klasa i przepraszam za to, ale dla mnie zawsze łatwiej jest się czegoś nauczyć, gdy widzę, jak działa w pełnym kontekście, więc postanowiłem nie zmniejszać tego. Jednak mimo że jest duży, jest zdecydowanie prosty i powinno być oczywiste, co dzieje się na zajęciach przy minimalnym wysiłku.

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;
    }
}

Oto kilka sposobów interakcji z klasą:

Ten kod:

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);
}

Daje następujące wyniki:

/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
Michael Sims
źródło