So I currently have two enums:
public enum AuthorizationLevel
{
FULL,
HALF,
NONE;
};
public enum DatabaseLoggingLevel
{
HIGH,
MED,
LOW,
AUTH_ONLY,
NONE
}
I want to be able to associate integers with the values in the enums so that I can have code like so:
if(databaseLoggingLevel < ClassName.DatabaseLoggingLevel.HIGH) return;
This is just so that certain logging is disabled when the level is less than HIGH. I thought about making a helper function that returns an integer value associated with each enum value with a switch statement, but that seems hacky. Is there something I am missing?
You can add an integer instance field to your enum, and add a parameterized constructor:
enum AuthorizationLevel {
FULL(1), HALF(2), NONE(3);
private final int level;
private AuthorizationLevel(int level) {
this.level = level;
}
public int getLevel() {
return level;
}
};
Note that there is an ordinal() method which will give you position of your enum constants, but you should avoid using it. Again, quoting Effective Java Item - 31 (Use instance fields instead of ordinal):
If the constants are reordered, the numberOfMusicians method will
break. If you want to add a second enum constant associated with an
int value that you’ve already used, you’re out of luck.
Also, you can’t add a constant for an int value without adding
constants for all intervening int values. For example, suppose you
want to add a constant representing a triple quartet, which consists
of twelve musicians. There is no standard term for an ensemble
consisting of eleven musicians, so you are forced to add a dummy
constant for the unused int value (11). At best, this is ugly. If many
int values are unused, it’s impractical.
Modify the constructor of your enum to add the Integer value.
public enum DatabaseLoggingLevel {
HIGH(1),
MED(2),
LOW(3),
AUTH_ONLY(4),
NONE(5);
private final Integer value;
//For getByValue(). See Rohit's comment
private static final DatabaseLoggingLevel[] VALUES = DatabaseLoggingLevel.values();
private DatabaseLoggingLevel(Integer value) {
this.value = value;
}
public Integer getValue() {
return this.value;
}
//Bonus : getter by value:
public static DatabaseLoggingLevel getByValue(Integer value) {
for(DatabaseLoggingLevel e: VALUES) {
if(e.getValue().equals(value)) {
return e;
}
}
return null;
}
}
public enum DatabaseLoggingLevel
{
HIGH(1),
MED(2),
LOW(3),
AUTH_ONLY(4),
NONE(5)
private int code;
private DatabaseLoggingLevel(int code) {
this.code = code;
}
public int getCode() { return code; }
}
Use the ordinal() method. It gives you the position of the Value in the enum.
Rather than programming this in terms of "enums are numbers", program this in terms of "enums are smart". You can associate numbers with enums (after all, enums are instances of regular Java classes), but make that number private. Then you can add this method to the enum:
public boolean isAboveOrEqualTo(DatabaseLoggingLevel level) {
...
}
Then your conditional would look like this:
if (databaseLoggingLevel.isAboveOrEqualTo(ClassName.DatabaseLoggingLevel.HIGH)) {
...
}
Here is an explanation of how to associate numbers with enums: link.
While both of the answers given already will do what you want I would recommend looking at Log4J as an alternative to rolling your own logging levels
http://www.tutorialspoint.com/log4j/log4j_overview.htm
Related
How to retrieve the enum name using value. By passing JOHN I need to retrieve the value as single
public enum Status {
JOHN("single"),
ALEX("married"),
MARTHA("not known");
}
Is it possible to have default value as well in-case value does not match?
To do this you need to define a constructor and a String variable. Then you could create a getter method to return the String variable:
public enum Status {
JOHN("single"),
ALEX("married"),
MARTHA("not known");
private String value;
private Status(String str) {
value = str;
}
public String getValue() {
return this.value;
}
}
And then to get the value you can do:
Status.JOHN.getValue()
To get the enum from a String you can use the valueOf() method:
Status.valueOf("JOHN").getValue();
However this will throw an error if the inputted String does not correspond to an enum. You could either wrap it in a try-catch to assign a default to it:
try {
Status.valueOf("JOHN").getValue();
} catch(IllegalArgumentException e) {
//Assign default
}
However a better design might be to put the possibilities into a HashMap and see if the inputted String is in the HashMap:
Map<String, Status> status = new HashMap<>();
status.put("JOHN", Y.JOHN);
if(status.containsKey(input)) {
//Do stuff
} else {
//Assign default
}
Define your enum like
enum Status {
JOHN("single"), ALEX("married"), MARTHA("not known");
private String value;
private Status(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
Now to fetch the value :
System.out.println(Status.JOHN.getValue());
Here define a parameterized constructor for each enum and store this value in a member variable.
A Java enum is an object, just like other objects in most ways. You can give it fields, methods, and constructors.
In this case, you can provide a marriage field and set it in a constructor just like you would for any other object.
Check out the official page on Java enums to see official examples, specifically the example with planets for your case. The Java Tutorials: Enum Types
Note also that you might not want to represent this specific data as an enum. You will be limited to only those 3 specific people by doing so. This is only appropriate if you know that you definitely will have only this specific list of people for the entire lifetime of this code. Otherwise you should just use a normal object.
A better idea might be to have a marriage enum and give your people a field of that type.
public enum MarriageStatus
{
Married,
NotMarried,
Unknown;
}
public class Person
{
String name = "Unknown";
MarriageStatus marriageStatus = MarriageStatus.Unknown;
}
I am currently processing a huge data input, including a lot of values, which I want to receive in getters for later use.
After writing a few methodes, I wondered if it might be a better idea to just use one get Method, with an enum-class containing all possible values, e.g.
public double getStat(StatType st) {
if(st != null)
return st.getValue();
}
instead of
public double getAvgReflection() {
return ...
}
public double getMaxLifesteal() {
return ...
}
Is there any convention for using either of the two possibilities?
Any dis/advantages?
Thanks in advance!
Using an Enum maxes it easier to add new stats, just add a constant in the Enum.
But all stats need to behave the same way, i.e. be doubles in your example. What happens if you want to add an int stat?
The "convention" you are asking about really boils down to the use and definition of your values. When you make the values Enums, then you must handle them as that type. Meaning, the fields in your class would have to be defined as such:
private MyEnum avgReflection;
private MyEnum maxLifesteal;
...
public MyEnum getAvgReflection {
return this.avgReflection;
}
And so forth.
Now, you could have your Enums return double values, but these values are static. I don't think you are concerned about static values, but, instead, perhaps a static set of values.
You then have two possible options: declare all possible parameters as fields, or create one aggregate field to hold all values and then use an Enum as an index:
public enum MyEnum {
averageReflection(0),
maximumLifeSteal(1);
private int value;
private MyEnum(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
}
...
private double[] attributes = new double[100]; // arbitrary initialization
public double getAttribute(MyEnum attribute) {
return this.attributes[attribute.getValue()];
}
The two restrictions on using an array (assuming you want primitive values and you are concerned about performance) is that all the values must be the same type, and the number of attributes will be set at compile time.
Additionally, you may just want to use a Map<String,double> or Map<MyEnum,double>, or even Map<MyEnum, Object>. A Map type will give you the ability to maintain a dynamically-sized set and possibly holding multiple types as well (with the costly overhead of converting your values).
You should base your decision on the amount of attributes you need to keep, the kind of overhead you are willing to tolerate, and your style.
This should be total obvious, but it isn't. Is there a way to get the value of a enum as in the example below?
example:
public enum Numbers
{
zero, one, two
}
//later on
Numbers numbers = Numbers.zero;
// this is the part that I can not figure out the java equivalent of?
int number = numbers.value();
Does this make sense what I am trying to do?
It is generally considered bad practice to rely on ordinal since it is based on the order of the enum constants. A better solution would be to pass information to each instance. Just write a constructor and method like this:
public enum Number {
ZERO(0), ONE(1), TWO(2);
private int value;
private Number(int value) {
this.value = value;
}
public int value() {
return value;
}
};
Then you use it like you want
Number numbers = Number.ZERO;
int number = numbers.value();
and you won't have to worry about the actual order of the code if you add Numbers later.
Note: It is idiomatic in Java for enum names to be singular and for constants to be uppercase.
Based on your comments it appears you need to map an integer value to your enum to integrate it into another part of your code.
Rather than relying on the ordering you really want to do this yourself:
public enum MyEnum {
ZERO(0), ONE(1), TWO(2);
private int mapping;
MyEnum(int mapping) {
this.mapping = mapping;
}
public int getMapping() {
return mapping;
}
}
You could then compare via:
MyEnum e = MyEnum.ZERO;
if (someInt == e.getMapping()) { ... }
(Or even just MyEnum.ZERO.getMapping() )
You can use the ordinal() method. However, this is discouraged / risky, since if you ever change the order or arrangements of your enums, it will fail. e.g., you change to powers of two
public enum Numbers {
zero, one, two, four
}
then four.ordinal() will be 3.
If you really want a number associated with the enum, you should define your own method, e.g. order() or whatever. In the initial implementation it could return ordinal(), but, when you add four in the future, you can update that method.
p.s. Standard style is to capitalize the enums, e.g. ZERO, ONE, etc...
It depends on what you need. Here are 2 use cases:
1) You will probably need to test the value of an incoming "Numbers". For this use case, a switch case is the best solution.
void myMethod(Numbers n){
switch(n){
case zero:
//do something
break;
case one:
//do something
break;
//etc.
}
}
2) You can calso need to assign a value to each Numbers and be able to retrieve it. For this use case, you can define a constructor for your enum
public enum Numbers
{
zero(0), one(1), two(2);
private int value;
private Numbers(int value){
this.value=value;
}
}
Then, in your code, you can get this value:
void myMethod(Numbers n){
int value = n.getValue();
//do something with this value...
}
Last remark : Your enum names don't follow the java convention. They should be named with uppercase letters and eventually character '_'. ex: ONE, TWO, THREE, ANOTHER_VALUE
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to get Enum Value from index in Java?
i have a enum like:
public enum EnumTest {
ONE, TWO, THREE
}
how i have a integer like 1=ONE 2=TWO 3=THREE
now i get a integer like 2 and want to generate the EnumTest from it and it should return TWO
how to do this?
Or, for more flexibility:
public enum EnumTest {
ONE(1), TWO(2), THREE(3);
private int value;
EnumTest(int value) {
this.value = value;
}
static EnumTest getByValue(int i) {
for (EnumTest e : values()) {
if (e.value == i) {
return e;
}
}
return null;
}
}
Think about future developpers which see this enum, if you leave an undocumented values() use, anybody can break it by adding new items. Because no documentation enforce the order of the elements.
You need to associate the int with a enum value.
You can do
static final EnumTest[] VALUE = { null, ONE, TWO, THREE };
return VALUE[num];
or
return EnumTest.values()[num-1];
or use a Map.
Get it like this EnumTest.values()[Number-1], where Number is your number (i.e. 1, 2, 3).
(Subtract 1 from the number because, for example, ONE will be at index 0, and EnumTest.values()[1] will give you TWO.)
If you just want the ordinal, here is some useful information:
you can get the ordinal of an enum constant with e.g. EnumTest.ONE.ordinal()
you can retrieve all enum constants with EnumTest.values()
From that, you can do what you want.
If you want to add a property with some arbitrary value, you can create a property + constructor + getter in your enum:
public enum EnumTest {
THREE(3), ONE(1), TWO(2);
private int val;
EnumTest(int val) { this.val = val; }
int getVal() { return val; }
}
This is more stable (values stay if you rename / insert / move them).
But are you sure you really need to get an int value? You should always work with the enum constants when possible e.g. EnumTest.THREE instead of 3.
I'd suggest to google for the various tutorials on java enums.
Try EnumTest.ordinal() for getting int values.
It will start from 0.
For getting enum from value, you can use EnumTest.values()[i].
Thanks.
Java states that the ordinal of the initial value is 0. Can I assume that when I create an enumeration like this :
public enum Direction {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, ...}
That the ordinal of TUESDAY is always 1, that of WEDNESDAY always 2, ...?
I'll be a bit more specific. I'm declaring an enumeration :
public enum Direction {UP,RIGHT,DOWN,LEFT}
Now there's a method to turn 90 degrees (clockwise). It's one line with ordinals :
direction = Direction.values()[direction.ordinal()+1 % Direction.values().length];
If I wouldn't use ordinals I would have to use switch statements or conditions :
switch (direction) {
case LEFT:newdirection = Direction.UP;
break;
etc...
}
There are a couple advantages to using ordinals :
shorter code
faster code (negligeable)
if a direction is added (for example DOWN_LEFT) the implementation doesn't necessarily have to change if you put the new direction at the right spot
What do you think?
Yes - see javadoc:
Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero).
Yes - but your code should not rely on it because then it will break when someone inserts Caturday.
Yes, however, relying on this makes your code brittle. If you ever change the order of the constants in the enum or add constants between them, the ordinals of some of the constants will change. So, it is for example not a good idea to store ordinal numbers in a database or a file, because if your source code changes, the data in the database or file will not be compatible anymore with your changed code.
A more robust solution is to explicitly store codes with each of your constants. For example:
public enum Status {
NEW(0),
PROCESSING(1),
OK(2),
ERROR(99);
private final int code;
private Status(int code) {
this.code = code;
}
// Get the code for an enum constant
public int getCode() {
return code;
}
// Given a code, get the corresponding enum constant
public static Status fromCode(int code) {
for (Status s : Status.values()) {
if (s.code == code) {
return s;
}
}
throw new IllegalArgumentException("Invalid code: " + code);
}
}
You can also enforce indexes like this:
enum Direction {
MONDAY(1),
TUESDAY(2);
// etc...
private int value;
private Direction(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
Yes. However, relying on that is not the best idea if you ever want to reorder or add new enums in different places, or if you find a reason to change an existing value. I find it better to give them an actual value/meaning aside from their ordinal value and name.
The problem with ordinals is that they depend on the order of declaration of the enum values. If at some point a new value is added to the enumeration, and it's added in the middle of the others, then the ordinals will change, invalidating all code that depended on a specific ordinal value.
If you absolutely must assign a fixed number to an ordinal value, this might be of use:
enum Directions {
NORTH(1),
SOUTH(2),
WEST(3),
EAST(4);
private int code;
Directions(int code) {
this.code = code;
}
public int getCode() {
return code;
}
}
In the above snippet, a code attribute is associated to each enumeration value, and you can be sure that it will always have the same value - the one passed in the constructor.