1

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?

6 Answers 6

6

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Yup exactly what I was looking for. I thought I remember this sort of syntax from somewhere. Thank you! I'll accept once the timer is up.
For enums, I typically recommend using the "final" keyword on fields, like private final int val;
@StormeHawke. Yeah, I missed that. I too prefer that way.
3

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;
  }
}

4 Comments

1. You are missing a semi-colon after the last enum constant. 2. Why use Integer instead of int? 3. DatabaseLoggingLevel.values() will create an array every time that method is called. It would better to cache the array in a field itself. 4. That method would really be a bonus, if the value is a string. In case of integer, I don't see any major use for it.
1: Edited. 2: I don't like literals, my personal choice. 3: Edited. 4: this one already exists : Enum#valueOf(String s);
2. I don't like literals - I'm talking about primitive type int instead of wrapper classes. And if you don't like primitive types, I feel sorry for you and your fellow programmers. You might end up creating unneccessary objects.
Primitives vs Objects is a debate that does not takes place in this thread. It is my personal design choice to always use Objects (except in consuming algorithms). When I want some performance, I code in C.
2
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; }

}

Comments

2

Use the ordinal() method. It gives you the position of the Value in the enum.

1 Comment

Quite dangerous. If you add one value in the enum, it will modify all ordinal().
2

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.

2 Comments

while this is certainly more OO, its verbosity is rather offputting compared to simple integer comparison. That is, actually writing the isAboveOrEqualTo method, not the actual comparison in the if statement.
@thatidiotguy The problem with exposing ints is that doing so gives away too much implementation that one presumably would rather hide behind the enum. Had the information hiding not been an objective, there would be no reason to introduce an enum in the first place, as symbolic int constants would be quite sufficient.
0

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

1 Comment

I use that for text logging. This is much more application specific, but thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.