284

I have a function which return a type int. However, I only have a value of the TAX enumeration.

How can I cast the TAX enumeration value to an int?

public enum TAX {
    NOTAX(0),SALESTAX(10),IMPORTEDTAX(5);

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

TAX var = TAX.NOTAX; // This value will differ

public int getTaxValue()
{
  // what do do here?
  // return (int)var;
}
vrbilgi
  • 5,703
  • 12
  • 44
  • 60
  • 1
    Possible duplicate of [How to match int to enum](http://stackoverflow.com/questions/7996335/how-to-match-int-to-enum) – malat Nov 18 '16 at 13:38

8 Answers8

388

You'd need to make the enum expose value somehow, e.g.

public enum Tax {
    NONE(0), SALES(10), IMPORT(5);

    private final int value;
    private Tax(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

...

public int getTaxValue() {
    Tax tax = Tax.NONE; // Or whatever
    return tax.getValue();
}

(I've changed the names to be a bit more conventional and readable, btw.)

This is assuming you want the value assigned in the constructor. If that's not what you want, you'll need to give us more information.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    I just tried it and realize it fails `myEnumValue = MyEnum.valueOf(myInt);` the arg has to be of type String - or is there something I am missing? – likejudo Sep 10 '14 at 22:58
  • 1
    This solution is worse than nothing. Seems enums in Java just shouldn't be used? Or has JDK 1.8 changed that? – ebyrob Nov 11 '16 at 16:10
  • @ebyrob: Given the voting, it seems like many people disagree with you, as I do. If you want a fixed set of values, enums are absolutely fine. – Jon Skeet Nov 11 '16 at 16:16
  • 1
    @ebyrob before saying anything about the solution, you should've taken a look at who answered it - SO God Jon Skeet himself!! – paradocslover May 12 '21 at 10:56
272

I prefer this:

public enum Color {

   White,

   Green,

   Blue,

   Purple,

   Orange,

   Red
}

then:

//cast enum to int
int color = Color.Blue.ordinal();
vivia
  • 2,983
  • 1
  • 13
  • 8
  • 39
    This is incorrect/not recommended by Joshua Bloch in his book Effective Java (2nd ed). See item 31. – user504342 Oct 13 '13 at 13:49
  • 1
    Using ordinal() method directly is not recommeneded. – tonga Dec 13 '13 at 16:20
  • 66
    @user504342 I do not have the 2nd edition of the book so can you please give us the gist of why it is not recommended? – likejudo Sep 10 '14 at 20:25
  • 26
    2 reasons: one, any association between the ordinal values and the constants will break if new constants are added, and two the API docs specifically recommend against it. – jordanpg Oct 28 '14 at 03:26
  • 14
    So clean and perfect. I see a few "don't do it" and "not recommended". I'll have to research on why it's considered bad. Some of the bloated samples look bad IMO. So much work to do such a simple task. – Herb Meehan May 20 '16 at 18:38
  • 7
    In a team, you're pretty sure on of your co-developer will add a value in the middle (worse at the beginning), or just sort them because they have nothing to do and completely mess the code using `.ordinal()` – Michael Laffargue May 03 '17 at 13:47
  • 5
    I am not concerned with the consequences of the numbers changing because I treat them as opaque values and do not log them to disk or communicate them outside the program. Under my circumstance, does any other criticism of `.ordinal()` apply? – William Entriken Jul 12 '19 at 17:41
  • For my ridiculous use case `.hashCode()` may provide the globally unique integer I am seeking. – William Entriken Aug 02 '19 at 19:27
  • An example of using ordinal values safely and correctly can be found here: https://stackoverflow.com/questions/8108980/java-using-enum-with-switch-statement Systems like Android limit us to passing int values through native communication mechanisms. When both ends of the communication are in the same application the alignment will not be an issue. So ordinal is a simple and safe solution. But if you have any doubt, assign explicit values as described in the accepted answer by Jon Skeet. That can never bite you. – Brent K. Jan 28 '20 at 13:56
  • 19
    I love how the javadoc for ordinal() says "most programmers will have no use for this method". Actually having a list of unique integers without having to assign them myself is often the main reason I use enums. They do not 'break' when new constants are added, provided you add them at the end. If you're using them in communications with outside programs and don't add the new value in the outside program then it's broken anyway. Been doing this for 20 years in C and never had any issues. Also, giving "it's not recommended" as the answer to "why is it not recommended" is not a reason :) – iforce2d Apr 10 '20 at 00:00
  • I like this method, it is simple, but the against comments sold me on the accepted answer. If you are the only developer on a project (for ever) then ordinal is fine, but all it would take is one person messing with the order of the enum (or you yourself forgetting the importance of the order) and it would create difficult to trace issues. Bite the bullet and do it the right way. – LordWabbit Jun 17 '20 at 11:10
  • I think it really depends what you're using the ordinal value for. Serialization would be dangerous, but as display order for a sort or something similar it could be harmless and changing the sort order by reordering items in code is less risky on a large list than updating dozens of magic numbers to non-sequential values. – Dan Is Fiddling By Firelight Mar 29 '23 at 15:13
24

Sometime some C# approach makes the life easier in Java world..:

class XLINK {
static final short PAYLOAD = 102, ACK = 103, PAYLOAD_AND_ACK = 104;
}
//Now is trivial to use it like a C# enum:
int rcv = XLINK.ACK;
Vladi
  • 464
  • 4
  • 6
  • For me this is the most desirable way to go. I get the benefits of enum (code clarity), a data type that is DB friendly, and I don't have to research 100 enum alternatives to do it the "android way". Simple and effective. – John Ward Mar 01 '17 at 15:08
  • Nice. It's as if the java enum is just completely disconnected from the reality of what an enum is used for... especially if people then start abusing it for things like singletons. This approach does have the disadvantage it doesn't have an easy way to get all values though. – Nyerguds Sep 18 '18 at 09:01
  • 4
    Doesn't this have the disadvantage of trying to pass an enum value to a method? You can no longer pass a XLINK to a method, because it doesn't represent anything concrete. You lose the typing into your method. The method signature would have to read short instead of XLINK. – Dustin Jensen Dec 20 '18 at 04:03
18

If you want the value you are assigning in the constructor, you need to add a method in the enum definition to return that value.

If you want a unique number that represent the enum value, you can use ordinal().

unholysampler
  • 17,141
  • 7
  • 47
  • 64
  • 2
    Be careful. There are many more developmental anti-patterns that rely on `ordinal()` than valid use cases for `ordinal()`. If you need to store a unique value for the `enum`, then just store the `enum`. There are EnumSets, Lists of Enums, EnumMaps, and nearly any other Enum collection you might want available. – Edwin Buck Nov 16 '11 at 19:57
  • 1
    @EdwinBuck: That is good to point out, I just wanted to mention the existence of `ordinal()` because the OP didn't make it clear what he wanted the int to actually be. – unholysampler Nov 16 '11 at 20:01
  • 1
    Don't get ordinal. Please check the enum api regarding this. Up-vote removed. – Hovercraft Full Of Eels Nov 16 '11 at 20:22
  • 3
    I wonder what peoples' thoughts are about the use of `ordinal()` internally within the enum itself. For example, say I have an enum called "`Season`" which contains the values `Spring`, `Summer`, `Autumn`, and `Winter`, and it has a public method called `next()` which returns `values()[(ordinal() + 1) % 4]` Externally, no code ever sees the ordinal number, and there will never be additional members in this enum, so it seems like a valid use-case. – Darrel Hoffman Oct 29 '13 at 19:52
  • 1
    @DarrelHoffman My feeling is that doing that is fine, since the only strong arguments I see against using `ordinal()` hinge on far flung code being broken by changes to the enum enumeration constants. If you're going to modify the enum's constants you'd have to be in that file already. Most enums are fairly short, and if it's not you should be checking the file more thoroughly anyway. In both cases you should probably have a unit test covering your `next()` method anyway. – Alan Hensley Jun 01 '16 at 16:26
3

Maybe it's better to use a String representation than an integer, because the String is still valid if values are added to the enum. You can use the enum's name() method to convert the enum value to a String an the enum's valueOf() method to create an enum representation from the String again. The following example shows how to convert the enum value to String and back (ValueType is an enum):

ValueType expected = ValueType.FLOAT;
String value = expected.name();

System.out.println("Name value: " + value);

ValueType actual = ValueType.valueOf(value);

if(expected.equals(actual)) System.out.println("Values are equal");
Mike
  • 3,094
  • 2
  • 12
  • 5
3
public enum ProfileType {
PRIVATE,
PUBLIC
}

private ProfileType profileType = ProfileType.PRIVATE;

If you want to get int from profileType you can simply do:

int profileTypeInt = profileType.ordinal();

Bijin Abraham
  • 1,709
  • 2
  • 11
  • 25
1
public enum Tax {

NONE(1), SALES(2), IMPORT(3);

private final int value;
    private Tax(int value) {
        this.value = value;
    }

    public String toString() {
        return Integer.toString(value);
    }
}

class Test {
    System.out.println(Tax.NONE);    //Just an example.
}
deHaar
  • 17,687
  • 10
  • 38
  • 51
1

A somewhat different approach (at least on Android) is to use the IntDef annotation to combine a set of int constants

@IntDef({NOTAX, SALESTAX, IMPORTEDTAX})
@interface TAX {}
int NOTAX = 0;
int SALESTAX = 10;
int IMPORTEDTAX = 5;

Use as function parameter:

void computeTax(@TAX int taxPercentage){...} 

or in a variable declaration:

@TAX int currentTax = IMPORTEDTAX;
mir
  • 371
  • 2
  • 5