85

I'm having trouble declaring an enum. What I'm trying to create is an enum for a 'DownloadType', where there are 3 download types (AUDIO, VIDEO, AUDIO_AND_VIDEO).

I have implemented the code as follows:

private enum DownloadType {
    AUDIO(0), VIDEO(1), AUDIO_AND_VIDEO(2);
    private final int value;

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

This works fine if I then use it like this:

DownloadType.AUDIO_AND_VIDEO.value;

However, I would like it so that I don't have to ask for the 'value'. I may be mistaken, but this is the way several classes work in Java such as Font, for example to set a font style, you use:

Font.PLAIN

Which returns an int value, we don't use:

Font.PLAIN.value
Cristian
  • 6,765
  • 7
  • 43
  • 64
  • 1
    You may simply use DownloadType.AUDIO_AND_VIDEO also unless you need value, am I missing something? – kosa Dec 09 '12 at 21:37
  • @Nambari If I System.out.println(DownloadType.AUDIO_AND_VIDEO) it returns "AUDIO_AND_VIDEO" which is apparently of type 'DownloadType', not int. – Cristian Dec 09 '12 at 21:38
  • 3
    I think you're confusing the purpose of enums. Why do you need the integer as well? – Jivings Dec 09 '12 at 21:39
  • Because I was thinking if I want to then get the type I could use 'if (downloadType == DownloadType.AUDIO){}', is that not right? – Cristian Dec 09 '12 at 21:40
  • 1
    It's the `toString()` method that gets invoked when you print your object. Also, _PLAIN_ is a constant in `Font` class, not an enum. – Andrew Logvinov Dec 09 '12 at 21:40

8 Answers8

111

Font.PLAIN is not an enum. It is just an int. If you need to take the value out of an enum, you can't avoid calling a method or using a .value, because enums are actually objects of its own type, not primitives.

If you truly only need an int, and you are already to accept that type-safety is lost the user may pass invalid values to your API, you may define those constants as int also:

public final class DownloadType {
    public static final int AUDIO = 0;
    public static final int VIDEO = 1;
    public static final int AUDIO_AND_VIDEO = 2;

    // If you have only static members and want to simulate a static
    // class in Java, then you can make the constructor private.
    private DownloadType() {}
}

By the way, the value field is actually redundant because there is also an .ordinal() method, so you could define the enum as:

enum DownloadType { AUDIO, VIDEO, AUDIO_AND_VIDEO }

and get the "value" using

DownloadType.AUDIO_AND_VIDEO.ordinal()

Edit: Corrected the code.. static class is not allowed in Java. See this SO answer with explanation and details on how to define static classes in Java.

Arnold Schrijver
  • 3,588
  • 3
  • 36
  • 65
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • Thanks for the clarification, this is making sense now. Instead of creating an enum, I'll make a public DownloadType { private static final int AUDIO = 0; } ... Should this be an InnerClass? Thanks for your answer. – Cristian Dec 09 '12 at 21:43
  • @Cristian: It mainly depends on how you want to access it. – kennytm Dec 09 '12 at 21:45
  • Thanks for your answers, was exactly what I was looking for - waiting 3 mins to accept – Cristian Dec 09 '12 at 21:46
  • Did you mean `public static final int AUDIO = 0;`. As far as I know `const` isn't a valid Java keyword. – Jade Sep 12 '13 at 18:28
  • 2
    ordinal may lead to a less stable system – hychou Jul 26 '17 at 14:33
  • I would not develop relying on the order of the `enum` values, so I discourage from using `DownloadType.AUDIO_AND_VIDEO.ordinal()`. – Marco Oct 09 '19 at 11:39
65

If you need to get the int value, just have a getter for the value in your ENUM:

private enum DownloadType {
    AUDIO(1), VIDEO(2), AUDIO_AND_VIDEO(3);
    private final int value;

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

    public int getValue() {
        return value;
    }
}

public static void main(String[] args) {
    System.out.println(DownloadType.AUDIO.getValue());           //returns 1
    System.out.println(DownloadType.VIDEO.getValue());           //returns 2
    System.out.println(DownloadType.AUDIO_AND_VIDEO.getValue()); //returns 3
}

Or you could simple use the ordinal() method, which would return the position of the enum constant in the enum.

private enum DownloadType {
    AUDIO(0), VIDEO(1), AUDIO_AND_VIDEO(2);
    //rest of the code
}

System.out.println(DownloadType.AUDIO.ordinal());            //returns 0
System.out.println(DownloadType.VIDEO.ordinal());            //returns 1
System.out.println(DownloadType.AUDIO_AND_VIDEO.ordinal()); //returns 2
ThomasW
  • 16,981
  • 4
  • 79
  • 106
PermGenError
  • 45,977
  • 8
  • 87
  • 106
  • 3
    Why do you need extra method when you can simply call .value and there is already a method ordinal() provided to get integer. – kosa Dec 09 '12 at 21:40
  • @Nambari umm, dint know enum has ordinal .. how stupid of me :P – PermGenError Dec 09 '12 at 21:41
  • @GanGnaMStYleOverFlowErroR Thanks for the answer, but I was actually looking to avoid calling .value, let alone creating another method and calling getValue() :) – Cristian Dec 09 '12 at 21:44
  • @GanGnaMStYleOverFlowErroR: That is correct, I could have clarified that in my comment. – kosa Dec 09 '12 at 21:45
  • @Nambari no problomo, thanks for letting me know about ordinal() :) – PermGenError Dec 09 '12 at 21:48
  • I would not develop relying on the order of the `enum` values, so I discourage from using `DownloadType.AUDIO_AND_VIDEO.ordinal()`. – Marco Oct 09 '19 at 11:40
18

First you should ask yourself the following question: Do you really need an int?

The purpose of enums is to have a collection of items (constants), that have a meaning in the code without relying on an external value (like an int). Enums in Java can be used as an argument on switch statments and they can safely be compared using "==" equality operator (among others).

Proposal 1 (no int needed) :

Often there is no need for an integer behind it, then simply use this:

private enum DownloadType{
    AUDIO, VIDEO, AUDIO_AND_VIDEO
}

Usage:

DownloadType downloadType = MyObj.getDownloadType();
if (downloadType == DownloadType.AUDIO) {
    //...
}
//or
switch (downloadType) {
  case AUDIO:  //...
          break;
  case VIDEO: //...
          break;
  case AUDIO_AND_VIDEO: //...
          break;
}

Proposal 2 (int needed) :

Nevertheless, sometimes it may be useful to convert an enum to an int (for instance if an external API expects int values). In this case I would advise to mark the methods as conversion methods using the toXxx()-Style. For printing override toString().

private enum DownloadType {
    AUDIO(2), VIDEO(5), AUDIO_AND_VIDEO(11);
    private final int code;

    private DownloadType(int code) {
        this.code = code;
    }

    public int toInt() {
        return code;
    }

    public String toString() {
        //only override toString, if the returned value has a meaning for the
        //human viewing this value 
        return String.valueOf(code);
    }
}

System.out.println(DownloadType.AUDIO.toInt());           //returns 2
System.out.println(DownloadType.AUDIO);                   //returns 2 via `toString/code`
System.out.println(DownloadType.AUDIO.ordinal());         //returns 0
System.out.println(DownloadType.AUDIO.name());            //returns AUDIO
System.out.println(DownloadType.VIDEO.toInt());           //returns 5
System.out.println(DownloadType.VIDEO.ordinal());         //returns 1
System.out.println(DownloadType.AUDIO_AND_VIDEO.toInt()); //returns 11

Summary

  • Don't use an Integer together with an enum if you don't have to.
  • Don't rely on using ordinal() for getting an integer of an enum, because this value may change, if you change the order (for example by inserting a value). If you are considering to use ordinal() it might be better to use proposal 1.
  • Normally don't use int constants instead of enums (like in the accepted answer), because you will loose type-safety.
Stéphane GRILLON
  • 11,140
  • 10
  • 85
  • 154
yonojoy
  • 5,486
  • 1
  • 31
  • 60
10

Simply call the ordinal() method on an enum value, to retrieve its corresponding number. There's no need to declare an addition attribute with its value, each enumerated value gets its own number by default, assigned starting from zero, incrementing by one for each value in the same order they were declared.

You shouldn't depend on the int value of an enum, only on its actual value. Enums in Java are a different kind of monster and are not like enums in C, where you depend on their integer code.

Regarding the example you provided in the question, Font.PLAIN works because that's just an integer constant of the Font class. If you absolutely need a (possibly changing) numeric code, then an enum is not the right tool for the job, better stick to numeric constants.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • 1
    I'm aware of ordinal(), but if I then want to change or specify a different order in future, this will cause problems. I'd like to specify the int value – Cristian Dec 09 '12 at 21:41
  • 1
    @Cristian you shouldn't depend on the int value of an enum, only on its actual value. Enums in Java are not like enums in C, where you depend on their integer code. – Óscar López Dec 09 '12 at 21:43
  • @Cristian and regarding the example you provided in the question `Font.PLAIN` works because that's just an integer constant of the `Font` class. If you absolutely need a (possibly changing) numeric code, then an `enum` is not the right tool for the job, better stick to numeric constants. – Óscar López Dec 09 '12 at 21:46
5

You can try this code .

private enum DownloadType {
    AUDIO , VIDEO , AUDIO_AND_VIDEO ;

}

You can use this enumeration as like this : DownloadType.AUDIO.ordinal(). Hope this code snippet will help you .

osimer pothe
  • 2,827
  • 14
  • 54
  • 92
3

If you are concatenating the enum with a string you can override toString method to return the int:

public String toString() {
    return value + "";
}

Then you could simply use:

String something = "foo" + DownloadType.AUDIO;

and the toString() method will be invoked.


Note that using toString() programmatically is generally considered poor practice - it is intended for human eyes only, however this is the only way to achieve what you're asking.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
3

Do you want to this code?

public static enum FieldIndex {
    HDB_TRX_ID,     //TRX ID
    HDB_SYS_ID      //SYSTEM ID
}

public String print(ArrayList<String> itemName){
    return itemName.get(FieldIndex.HDB_TRX_ID.ordinal());
}
Hadrien01
  • 124
  • 3
  • 12
seyeon
  • 4,092
  • 2
  • 15
  • 12
2

In my opinion the most readable version

public enum PIN_PULL_RESISTANCE {
    PULL_UP {
        @Override
        public int getValue() {
            return 1;
        }
    },
    PULL_DOWN {
        @Override
        public int getValue() {
            return 0;
        }
    };

    public abstract int getValue();
}