Java enums with int values

Storing integer values as constants in Enum manner in java [duplicate]

That won’t compile; you’ve defined «SIGN_CREATE» twice. Also, those aren’t constants — they’re not «final».

6 Answers 6

Well, you can’t quite do it that way. PAGE.SIGN_CREATE will never return 1; it will return PAGE.SIGN_CREATE . That’s the point of enumerated types.

However, if you’re willing to add a few keystrokes, you can add fields to your enums, like this:

 public enum PAGE < SIGN_CREATE(0), SIGN_CREATE_BONUS(1), HOME_SCREEN(2), REGISTER_SCREEN(3); private final int value; PAGE(final int newValue) < value = newValue; >public int getValue() < return value; >> 

And then you call PAGE.SIGN_CREATE.getValue() to get 0.

This is actually not true. You can do PAGE.SIGN_CREATE.ordinal(). This would return 0. Probably this anwser is related to a java version, that didn’t have this feature, yet.

What of you want to mix numbers and chars up within a single enum? E.g. if I want an enum to store 0, 1 and X? Thank you!!

@BlairHippo: Can I do something like PAGE pageEnum = PAGE(0) . In simple words I have a value with me and I want to get the corresponding enum with selected value. Can you answer?

The most common valid reason for wanting an integer constant associated with each enum value is to interoperate with some other component which still expects those integers (e.g. a serialization protocol which you can’t change, or the enums represent columns in a table, etc).

Читайте также:  Java reference internal class

In almost all cases I suggest using an EnumMap instead. It decouples the components more completely, if that was the concern, or if the enums represent column indices or something similar, you can easily make changes later on (or even at runtime if need be).

 private final EnumMap pageIndexes = new EnumMap(Page.class); pageIndexes.put(Page.SIGN_CREATE, 1); //etc., . int createIndex = pageIndexes.get(Page.SIGN_CREATE); 

It’s typically incredibly efficient, too.

Adding data like this to the enum instance itself can be very powerful, but is more often than not abused.

Edit: Just realized Bloch addressed this in Effective Java / 2nd edition, in Item 33: Use EnumMap instead of ordinal indexing.

Источник

is it possible to define an enum with int identifiers?

My question is «is it possible to have an int identifier in an enum?» I’m developping a java program and I need to have identifiers that contains numbers and letters but eclips doesn’t accept it. for exapmle public enum Tag < 5F25, 4F, . . . >Do anyone know if there is any way to solve this problem! Thank you

Your problem is «an identifier starting with an integer», as you can see in @GGrecs answer, having an int somewhere else isn’t a problem.

3 Answers 3

Enum instances must obey the same java language naming restrictions as other identifiers — they can’t start with a number.

If you absolutely must have hex in the name, prefix them all with a letter/word, for example the enum class itself:

or maybe with an underscore and all-caps:

I support using an underscore as the prefix, so usage looks like Tag._5F25 with no redundancy. Will probably have to modify the SonarQube regex for RSPEC-115 though.

You’re trying to bend the laws and conventions of programming. I suggest you take a different approach.

Enums can have constructors. They are usually private, because «instances» of the enum are created inside it. You can provide any info you want (e.g. id, name, keyword etc.).

In this example, I’ve implemented the enum with just one parameter in the constructor, which is the unique ID you’re needing.

public enum Tag < TAG_1(1), TAG_2(2), TAG_3(3); private final int id; private Tag(final int id) < this.id = id; >public int id() // Objective C style. Can be getId() < return id; >/** * Bonus method: get a Tag for a specific ID. * * e.g. Tag tagWithId2 = Tag.getTagForId(2); */ public static Tag getTagForId(final int id) < for (final Tag tag : values()) if (tag.id == id) return tag; return null; >> 

Источник

Enum with int value in Java

If you want attributes for your enum you need to define it like this:

public enum Foo < BAR (0), BAZ (1), FII (10); private final int index; Foo(int index) < this.index = index; >public int index() < return index; >> 
public static void main(String[] args) < for (Foo f : Foo.values()) < System.out.printf("%s has index %d%n", f, f.index()); >> 

The thing to realise is that enum is just a shortcut for creating a class, so you can add whatever attributes and methods you want to the class.

If you don’t want to define any methods on your enum you could change the scope of the member variables and make them public , but that’s not what they do in the example on the Sun website.

+1 for including the accessor 🙂 Note that to get to the numerical value, you’d have to use Foo.BAR.index()

Note also, that if you want to get to the enum from the int code, you shoudl also add a static method that do the reverse mapping (with a switch or a map).

@penpen — a switch is a bummer to maintain; do the map, or just do a linear search, it’s not that bad (except when it is)

I would not call this index but val instead as for example the index (ordinal) of FII in this code is 2 (assuming zero based indexing) while its value is 10.

If you have a contiguous range of values, and all you need is the integer value, you can just declare the enum minimally:

and then obtain the int value as follows:

int numberOne = NUMBERZ.ONE.ordinal(); 

However, if you need a discontiguous range (as in your example, where you jump from 1 to 10) then you will need to write your own enum constructor which sets your own member variable, and provide a get method for that variable, as described in the other answers here.

Источник

Cast Int to enum in Java

Try MyEnum.values()[x] where x must be 0 or 1 , i.e. a valid ordinal for that enum.

Note that in Java enums actually are classes (and enum values thus are objects) and thus you can’t cast an int or even Integer to an enum.

@PeterLawrey Just for completeness, can you explain why it should be slow? I see no obvious reason for it.

@Tarrasch as arrays are mutable, values() must return a copy of the array of elements just in case you happen to change it. Creating this copy each time is relatively expensive.

@PeterLawrey I’ve been using to much haskell lately (where everything is immutable)! Thanks for your clear and concise explanation. 🙂

MyEnum.values()[x] is an expensive operation. If the performance is a concern, you may want to do something like this:

public enum MyEnum < EnumValue1, EnumValue2; public static MyEnum fromInteger(int x) < switch(x) < case 0: return EnumValue1; case 1: return EnumValue2; >return null; > > 

If you want to avoid the switch maintenance, then on the using class: private final MyEnum[] myEnumValues = MyEnum.values(); Then usage: myEnum = myEnumValues[i];

@GiliNachum said it in a weird way, but the problem with this solution is maintainability. It goes against the DRY principle, which means whenever the enum values is changed (reordered, value(s) added, value(s) removed) the switch statement has to simultaneously be updated. Gili’s comment forces Java to maintain consistency with the list of enum values, changes to the enum values doesn’t affect that approach at all.

@LorenzoPolidori, Can you explain why you regard MyEnum.values()[x] as an expensive operation. I don’t know how it works in details, but to me it seems like accessing an element in an Array would be no big deal, aka constant time. If the array has to be build it takes O(n) time, which is the same runnning time as your solution.

@brunsgaard I assume values() generates a new array each time, because arrays are mutable so it wouldn’t be safe to return the same one multiple times. Switch statements are not necessarily O(n), they can be compiled to jump tables. So Lorenzo’s claims seem justified.

@Johnson Gili’s version doesn’t require any additional code changes outside of the changes in the Enum declaration. If you add a new item to the enum, myEnum = myEnumValues[i] will still return the i th item in the Enum without changes.

If you want to give your integer values, you can use a structure like below

public enum A < B(0), C(10), None(11); int id; private A(int i)public int GetID() public boolean IsEmpty() public boolean Compare(int i) public static A GetValue(int _id) < A[] As = A.values(); for(int i = 0; i < As.length; i++) < if(As[i].Compare(_id)) return As[i]; >return A.None; > > 

Also, this seems to be the only answer that works if you want a sparse (or repeated) set of integer values rather than using the default ordinals from 0..(count-1). That can be important if you’re interacting with existing code, such as over a network.

Worth pointing out that as in the above answers, caching the result of values() is probably worthwhile, so as to avoid a memory allocation and arraycopy every time you invoke it.

And, depending on the length of your enum, you may want to create a HashMap or use a binary search or something for this lookup, rather than doing a linear search every time.

This should be the right way and best practice to convert int to enum, and i think you can simplify the problem by public static A GetValue(int _id) < for(A a:A.values() < if(a.getId()==_id) < return a; >> return null; > Get rid of the None, isEmpty() and compare() stuff.

You can try like this.
Create Class with element id.

 public Enum MyEnum < THIS(5), THAT(16), THE_OTHER(35); private int id; // Could be other data type besides int private MyEnum(int id) < this.id = id; >public static MyEnum fromId(int id) < for (MyEnum type : values()) < if (type.getId() == id) < return type; >> return null; > > 

Now Fetch this Enum using id as int.

MyEnum myEnum = MyEnum.fromId(5); 

I cache the values and create a simple static access method:

public static enum EnumAttributeType < ENUM_1, ENUM_2; private static EnumAttributeType[] values = null; public static EnumAttributeType fromInt(int i) < if(EnumAttributeType.values == null) < EnumAttributeType.values = EnumAttributeType.values(); >return EnumAttributeType.values[i]; > > 

This is solution I use now. But IMHO it is less confusing if you don’t give the field values the same name as the method values() . I uses cachedValues for field name.

Efficient and elegant; copied and pasted into my project 🙂 The only thing I changed is the fromInt(int i), which I’m just called from(int i) because it’s a bit redundant to have int twice in the signature.

@kaiser there’s no place to get values() «from the beginning». The enum constructors are per enum value so in those constructors this.values() gives —java.lang.NullPointerException: Cannot invoke «[LFooBar;.clone()» because «FooBar.$VALUES» is null

I think that fromOrdinal(int) might be a better name since there’s a lot of alternative solutions like @Doctor’s answer here that use a synthetic/explicit int value, like id or value .

Java enums don’t have the same kind of enum-to-int mapping that they do in C++.

That said, all enums have a values method that returns an array of possible enum values, so

MyEnum enumValue = MyEnum.values()[x]; 

should work. It’s a little nasty and it might be better to not try and convert from int s to Enum s (or vice versa) if possible.

This not something that is usually done, so I would reconsider. But having said that, the fundamental operations are: int —> enum using EnumType.values()[intNum] , and enum —> int using enumInst.ordinal() .

However, since any implementation of values() has no choice but to give you a copy of the array (java arrays are never read-only), you would be better served using an EnumMap to cache the enum —> int mapping.

Re «This not something that is usually done»: Common case where it is useful: enum corresponds to int values stored in a database.

@ToolmakerSteve you are absolutely right that the mappings are required. But would you want to leave that sort of encoding to some O-R mapper or some toolkit/library?

Use MyEnum enumValue = MyEnum.values()[x];

Here’s the solution I plan to go with. Not only does this work with non-sequential integers, but it should work with any other data type you may want to use as the underlying id for your enum values.

public Enum MyEnum < THIS(5), THAT(16), THE_OTHER(35); private int id; // Could be other data type besides int private MyEnum(int id) < this.id = id; >public int getId() < return this.id; >public static Map buildMap() < Mapmap = new HashMap(); MyEnum[] values = MyEnum.values(); for (MyEnum value : values) < map.put(value.getId(), value); >return map; > > 

I only need to convert id’s to enums at specific times (when loading data from a file), so there’s no reason for me to keep the Map in memory at all times. If you do need the map to be accessible at all times, you can always cache it as a static member of your Enum class.

Источник

Оцените статью