Java Enum return Int
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
Solution 1:
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.
Solution 2:
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
Solution 3:
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 useordinal()
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.
Solution 4:
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.