Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>These are the main arguments for <a href="http://download-llnw.oracle.com/javase/1.5.0/docs/guide/language/enums.html" rel="nofollow noreferrer"><code>enum</code></a>, <a href="http://java.sun.com/javase/6/docs/api/java/util/EnumMap.html" rel="nofollow noreferrer"><code>EnumMap</code></a>, and <a href="http://java.sun.com/javase/6/docs/api/java/util/EnumSet.html" rel="nofollow noreferrer"><code>EnumSet</code></a> by short examples.</p> <h3>The case for <code>enum</code></h3> <p>As of Java 6, <a href="http://java.sun.com/javase/6/docs/api/java/util/Calendar.html" rel="nofollow noreferrer"><code>java.util.Calendar</code></a> is an example of a messy class that could've benefited a lot from using <code>enum</code> (among other improvements).</p> <p>Currently <code>Calendar</code> defines the following constants (<a href="http://java.sun.com/javase/6/docs/api/constant-values.html#java.util.Calendar.JANUARY" rel="nofollow noreferrer">among many others</a>):</p> <pre><code>// int constant antipattern from java.util.Calendar public static final int JANUARY = 0; public static final int FEBRUARY = 1; ... public static final int SUNDAY = 1; public static final int MONDAY = 2; ... </code></pre> <p>These are all <code>int</code>, even though they obviously represent different conceptual entities.</p> <p>The following are some serious consequences:</p> <ul> <li><em>It's brittle</em>; care must be taken to assign different numbers whenever needed. <ul> <li>If by mistake we set <code>MONDAY = 0;</code>, <code>SUNDAY = 0;</code>, then we have <code>MONDAY == SUNDAY</code></li> </ul></li> <li><em>There is no namespace and no type-safety</em>, since everything is just an <code>int</code>: <ul> <li>We can <code>setMonth(JANUARY)</code>, but we can also <code>setMonth(THURSDAY)</code> or <code>setMonth(42)</code></li> <li>Who knows what <a href="http://java.sun.com/javase/6/docs/api/java/util/Calendar.html#set%28int,%20int,%20int,%20int,%20int,%20int%29" rel="nofollow noreferrer"><code>set(int,int,int,int,int,int)</code></a> (a real method!) does!</li> </ul></li> </ul> <p>By contrast, we could have something like this instead:</p> <pre><code>// Hypothetical enums for a Calendar library enum Month { JANUARY, FEBRUARY, ... } enum DayOfWeek { SUNDAY, MONDAY, ... } </code></pre> <p>Now we never have to worry about <code>MONDAY == SUNDAY</code> (it can never happen!), and since <code>Month</code> and <code>DayOfWeek</code> are different types, <code>setMonth(MONDAY)</code> does not compile.</p> <p>Additionally, here are some before-and-after codes:</p> <pre><code>// BEFORE with int constants for (int month = JANUARY; month &lt;= DECEMBER; month++) { ... } </code></pre> <p>Here we're making all sorts of assumptions, e.g. <code>JANUARY + 1 == FEBRUARY</code>, etc. On the other hand, the <code>enum</code> counterpart is both more concise, more readable, and makes less assumptions (and therefore less chance for bugs):</p> <pre><code>// AFTER with enum for (Month month : Month.values()) { ... } </code></pre> <hr> <h3>The case for instance fields</h3> <p>In Java, <code>enum</code> is a <code>class</code> that has many special properties, but a <code>class</code> nonetheless, allowing you to define instance methods and fields if necessary.</p> <p>Consider the following example:</p> <pre><code>// BEFORE: with int constants public static final int NORTH = 0; public static final int EAST = 1; public static final int SOUTH = 2; public static final int WEST = 3; public static int degreeFor(int direction) { return direction * 90; // quite an assumption! // must be kept in-sync with the int constants! } //... for (int dir = NORTH; dir &lt;= WEST; dir++) { ... degreeFor(dir) ... } </code></pre> <p>On the other hand, with <code>enum</code> you can write something like this:</p> <pre><code>enum Direction { NORTH(0), EAST(90), SOUTH(180), WEST(270); // so obvious! so easy to read! so easy to write! so easy to maintain! private final int degree; Direction(int degree) { this.degree = degree; } public int getDegree() { return degree; } } //... for (Direction dir : Direction.values()) { ... dir.getDegree() ... } </code></pre> <h3>The case for instance methods</h3> <p>Consider the following example:</p> <pre><code>static int apply(int op1, int op2, int operator) { switch (operator) { case PLUS : return op1 + op2; case MINUS : return op1 - op2; case ... default: throw new IllegalArgumentException("Unknown operator!"); } } </code></pre> <p>As shown in previous example, <code>enum</code> in Java can have instance methods, but not only that but each constant can have its own specific <code>@Override</code> as well. This is shown in the following code:</p> <pre><code>enum Operator { PLUS { int apply(int op1, int op2) { return op1 + op2; } }, MINUS { int apply(int op1, int op2) { return op1 - op2; } }, ... ; abstract int apply(int op1, int op2); } </code></pre> <hr> <h3>The case for <code>EnumMap</code></h3> <p>Here's a quote from <em>Effective Java 2nd Edition</em>:</p> <blockquote> <p>Never derive a value associated with an <code>enum</code> from its <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Enum.html#ordinal%28%29" rel="nofollow noreferrer"><code>ordinal()</code></a>; store it in an instance field instead. (<em>Item 31: Use instance fields instead of ordinals</em>) It is rarely appropriate to use ordinals to index arrays: use <code>EnumMap</code> instead. The general principle is that application programmers should rarely, if ever, use <code>Enum.ordinal</code>. (<em>Item 33: Use <code>EnumMap</code> instead of ordinal indexing</em>)</p> </blockquote> <p>Essentially where as before you may have something like this:</p> <pre><code>// BEFORE, with int constants and array indexing Employee[] employeeOfTheMonth = ... employeeOfTheMonth[JANUARY] = jamesBond; </code></pre> <p>Now you can have:</p> <pre><code>// AFTER, with enum and EnumMap Map&lt;Month, Employee&gt; employeeOfTheMonth = ... employeeOfTheMonth.put(Month.JANUARY, jamesBond); </code></pre> <hr> <h3>The case for <code>EnumSet</code></h3> <p>Power of two <code>int</code> constants are often used e.g. in C++ to denote bit sets. This relies on <a href="http://en.wikipedia.org/wiki/Bitwise_operations" rel="nofollow noreferrer">bitwise operations</a>. An example may look something like this:</p> <pre><code>public static final int BUTTON_A = 1; public static final int BUTTON_B = 2; public static final int BUTTON_X = 4; public static final int BUTTON_Y = 8; int buttonState = BUTTON_A | BUTTON_X; // A &amp; X are pressed! if ((buttonState &amp; BUTTON_B) != 0) { // B is pressed... ... } </code></pre> <p>With <code>enum</code> and <code>EnumSet</code>, this can look something like this:</p> <pre><code>enum Button { A, B, X, Y; } Set&lt;Button&gt; buttonState = EnumSet.of(Button.A, Button.X); // A &amp; X are pressed! if (buttonState.contains(Button.B)) { // B is pressed... ... } </code></pre> <h3>References</h3> <ul> <li><a href="http://docs.oracle.com/javase/1.5.0/docs/guide/language/enums.html" rel="nofollow noreferrer">Java Language Guide/Enums</a> -- quite complete treatment with many examples</li> </ul> <h3>See also</h3> <ul> <li><em>Effective Java 2nd Edition</em> <ul> <li>Item 30: Use <code>enum</code> instead of <code>int</code> constants</li> <li>Item 31: Use instance fields instead of ordinals</li> <li>Item 32: Use <a href="http://java.sun.com/javase/6/docs/api/java/lang/EnumSet.html" rel="nofollow noreferrer"><code>EnumSet</code></a> instead of bit fields</li> <li>Item 33: Use <a href="http://java.sun.com/javase/6/docs/api/java/util/EnumMap.html" rel="nofollow noreferrer"><code>EnumMap</code></a> instead of ordinal indexing</li> </ul></li> </ul> <h3>Related questions</h3> <ul> <li><a href="https://stackoverflow.com/questions/2077634/enum-in-java-advantages">Enum in Java. Advantages?</a></li> <li><a href="https://stackoverflow.com/questions/2765687/is-there-a-a-c-like-way-to-get-item-number-from-enum-in-java">Is there a a C-like way to get item number from enum in java ?</a> -- yes, <code>ordinal()</code>, however...</li> <li><a href="https://stackoverflow.com/questions/1574580/is-it-bad-practice-to-use-an-enums-ordinal-value-to-index-an-array-in-java">Is it bad practice to use an Enum’s ordinal value to index an array in Java?</a> -- most probably, yes!</li> <li><a href="https://stackoverflow.com/questions/3360283/java-number-for-each-enum-item">[java] Number for each enum item?</a> -- a prime candidate for <code>EnumSet</code>!</li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload