UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

104 lines (96 loc) 15.8 kB
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"><head><title>Enumerations</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="Enumerations"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-5-SECT-5"/>Enumerations</h1></div></div></div><p>Now that we’ve covered the basics of classes, we can talk a bit more in depth about <span class="emphasis"><em>enumerations</em></span>. As we’ve discussed, an enumeration is an object type in the Java language that is limited to an explicit set of values. The values have an order that is defined by their order of declaration in the code, and have a correspondence with a string name that is the same as their declared name in the source code.</p><p>We’ve already seen a couple of examples of enumerations used in place of static identifiers. For example:</p><a id="I_5_tt276"/><pre class="programlisting"> <code class="kd">enum</code> <code class="n">Weekday</code> <code class="o">{</code> <code class="n">Sunday</code><code class="o">,</code> <code class="n">Monday</code><code class="o">,</code> <code class="n">Tuesday</code><code class="o">,</code> <code class="n">Wednesday</code><code class="o">,</code> <code class="n">Thursday</code><code class="o">,</code> <code class="n">Friday</code><code class="o">,</code> <code class="n">Saturday</code> <code class="o">}</code> <code class="c1">// usage</code> <code class="n">setDay</code><code class="o">(</code> <code class="n">Weekday</code><code class="o">.</code><code class="na">Sunday</code> <code class="o">);</code></pre><p>Let’s take a look at what the Java compiler is actually generating for the enum. It is a regular compiled Java class, in this case named <code class="literal">Weekday</code>, so we can display it with the <code class="literal">javap</code> command like so:</p><a id="I_5_tt277"/><pre class="programlisting"> <code class="o">%</code> <strong class="userinput"><code><code class="n">javap</code> <code class="n">Weekday</code></code></strong> <code class="kd">public</code> <code class="kd">final</code> <code class="kd">class</code> <code class="nc">Weekday</code> <code class="kd">extends</code> <code class="n">java</code><code class="o">.</code><code class="na">lang</code><code class="o">.</code><code class="na">Enum</code> <code class="o">{</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kd">final</code> <code class="n">Weekday</code> <code class="n">Sunday</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kd">final</code> <code class="n">Weekday</code> <code class="n">Monday</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kd">final</code> <code class="n">Weekday</code> <code class="n">Tuesday</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kd">final</code> <code class="n">Weekday</code> <code class="n">Wednesday</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kd">final</code> <code class="n">Weekday</code> <code class="n">Thursday</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kd">final</code> <code class="n">Weekday</code> <code class="n">Friday</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kd">final</code> <code class="n">Weekday</code> <code class="n">Saturday</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kd">final</code> <code class="n">Weekday</code><code class="o">[]</code> <code class="nf">values</code><code class="o">();</code> <code class="kd">public</code> <code class="kd">static</code> <code class="n">Weekday</code> <code class="nf">valueOf</code><code class="o">(</code><code class="n">java</code><code class="o">.</code><code class="na">lang</code><code class="o">.</code><code class="na">String</code><code class="o">);</code> <code class="o">}</code></pre><p><code class="literal">Weekday</code> is a subclass of the <code class="literal">Enum</code> type with seven static, final, “constant” object references corresponding to our seven enumerated values. Each of the enumerated values is of type <code class="literal">Weekday</code>. The Java compiler does not let us extend this class or create any other instances of this type. The only instances of <code class="literal">Weekday</code> that will ever exist are the seven enumerated values. This is what gives enumerations their type safety. A method expecting a <code class="literal">Weekday</code> can be given one of only seven values. Unlike a numeric constant identifier, no value other than a <code class="literal">Weekday</code> will work. As we saw in <a class="xref" href="ch04.html" title="Chapter 4. The Java Language">Chapter 4</a>, enumerations (unlike most objects) can also be used in <code class="literal">switch</code> statements with all the same benefits.</p><p>Because enumerations are static values, they can be imported with the Java <span class="emphasis"><em>static import</em></span>, saving us some typing:</p><a id="I_5_tt278"/><pre class="programlisting"> <code class="kn">import</code> <code class="nn">static</code> <code class="n">mypackage</code><code class="o">.</code><code class="na">Weekday</code><code class="o">.*;</code> <code class="o">...</code> <code class="n">setDay</code><code class="o">(</code> <code class="n">Friday</code> <code class="o">);</code> <code class="n">setDeadline</code><code class="o">(</code> <code class="n">Sunday</code> <code class="o">);</code></pre><p>We should also mention that enumerations can be declared not only at the “top level” alongside classes, but within classes or interfaces as well. In this case, they act just like inner classes (see <a class="xref" href="ch06.html" title="Chapter 6. Relationships Among Classes">Chapter 6</a>).</p><div class="sect2" title="Enum Values"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-5-SECT-5.1"/>Enum Values</h2></div></div></div><p><a id="I_indexterm5_id693533" class="indexterm"/> <a id="I_indexterm5_id693541" class="indexterm"/>You can get the ordered list of enum values for a type with the static <a id="I_indexterm5_id693552" class="indexterm"/><code class="literal">values()</code> method.</p><a id="I_5_tt279"/><pre class="programlisting"> <code class="n">Weekday</code> <code class="o">[]</code> <code class="n">weekdays</code> <code class="o">=</code> <code class="n">Weekday</code><code class="o">.</code><code class="na">values</code><code class="o">();</code></pre><p>The <a id="I_indexterm5_id693574" class="indexterm"/><code class="literal">compareTo()</code> method of an enum compares an enum value to another value of the same enum type and returns an integer less than zero, zero, or greater than zero, indicating whether the target enum is “less than,” “equal to,” or “greater than” the order of the reference enum. This doesn’t mean much for our <code class="literal">Weekday</code>s, but it might be useful for values that have a more numeric meaning or a (noncyclic) scale of some kind. For example:</p><a id="I_5_tt280"/><pre class="programlisting"> <code class="n">Level</code> <code class="n">level</code> <code class="o">=</code> <code class="n">Level</code><code class="o">.</code><code class="na">LOW</code><code class="o">;</code> <code class="n">Level</code> <code class="n">anotherLevel</code> <code class="o">=</code> <code class="n">Level</code><code class="o">.</code><code class="na">HIGH</code><code class="o">;</code> <code class="k">if</code> <code class="o">(</code> <code class="n">level</code><code class="o">.</code><code class="na">compareTo</code><code class="o">(</code> <code class="n">anotherLevel</code> <code class="o">)</code> <code class="o">&gt;</code> <code class="mi">0</code> <code class="o">)</code> <code class="c1">// true</code> <code class="n">doSomething</code><code class="o">();</code></pre><p>We mentioned that enum values have a string correspondence for their names. You can get the string name of the value (which is exactly the same as it is declared in the source code) with the <a id="I_indexterm5_id693611" class="indexterm"/><code class="literal">name()</code> method. Going the other direction, you can “look up” any enum value by its class type and string name using the static <a id="I_indexterm5_id693624" class="indexterm"/><code class="literal">Enum.valueOf()</code> method:</p><a id="I_5_tt281"/><pre class="programlisting"> <code class="n">String</code> <code class="n">mondayString</code> <code class="o">=</code> <code class="n">Weekday</code><code class="o">.</code><code class="na">Monday</code><code class="o">.</code><code class="na">name</code><code class="o">();</code> <code class="c1">// "Monday"</code> <code class="n">Weekday</code> <code class="n">mondayWeekday</code> <code class="o">=</code> <code class="n">Enum</code><code class="o">.</code><code class="na">valueOf</code><code class="o">(</code> <code class="n">Weekday</code><code class="o">.</code><code class="na">class</code><code class="o">,</code> <code class="s">"Monday"</code> <code class="o">);</code></pre><p>The <code class="literal">name()</code> value is also used by the <code class="literal">toString()</code> method of the value, so printing an enum value does what you’d expect.</p></div><div class="sect2" title="Customizing Enumerations"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-5-SECT-5.2"/>Customizing Enumerations</h2></div></div></div><p><a id="idx10227" class="indexterm"/> <a id="idx10244" class="indexterm"/>We said that the <a id="I_indexterm5_id693692" class="indexterm"/><code class="literal">java.lang.Enum</code> type cannot be directly extended and that you can’t create new instances of enum types. However, you can add things to the generated enumeration class when it’s declared. For example, the enumeration <a id="I_indexterm5_id693706" class="indexterm"/><code class="literal">java.util.concurrent.TimeUnit</code>, which has identifiers for time units such as SECONDS, MILLISECONDS, and MICROSECONDS, has a <code class="literal">sleep()</code> method that interprets its argument in the correct time scale:</p><a id="I_5_tt282"/><pre class="programlisting"> <code class="kn">import</code> <code class="nn">static</code> <code class="n">java</code><code class="o">.</code><code class="na">util</code><code class="o">.</code><code class="na">concurrent</code><code class="o">.</code><code class="na">TimeUnit</code><code class="o">.*;</code> <code class="n">SECONDS</code><code class="o">.</code><code class="na">sleep</code><code class="o">(</code> <code class="mi">5</code> <code class="o">);</code> <code class="c1">// sleep 5 seconds</code></pre><p>Enumerations can have values with constructors, methods, and fields just like other classes. For the most part, this is straightforward; you just add a semicolon after the enum values and then add your additional class members. Let’s add a “fun” value and accessor method to our weekdays:</p><a id="I_5_tt283"/><pre class="programlisting"> <code class="kd">public</code> <code class="kd">enum</code> <code class="n">Weekday</code> <code class="o">{</code> <code class="n">Sunday</code><code class="o">(</code><code class="mi">8</code><code class="o">),</code> <code class="n">Monday</code><code class="o">(</code><code class="mi">0</code><code class="o">),</code> <code class="n">Tuesday</code><code class="o">(</code><code class="mi">1</code><code class="o">),</code> <code class="n">Wednesday</code><code class="o">(</code><code class="mi">2</code><code class="o">),</code> <code class="n">Thursday</code><code class="o">(</code><code class="mi">4</code><code class="o">),</code> <code class="n">Friday</code><code class="o">(</code><code class="mi">6</code><code class="o">),</code> <code class="n">Saturday</code><code class="o">(</code><code class="mi">10</code><code class="o">)</code> <code class="o">;</code> <code class="kt">int</code> <code class="n">fun</code><code class="o">;</code> <code class="n">Weekday</code><code class="o">(</code> <code class="kt">int</code> <code class="n">fun</code> <code class="o">)</code> <code class="o">{</code> <code class="k">this</code><code class="o">.</code><code class="na">fun</code> <code class="o">=</code> <code class="n">fun</code><code class="o">;</code> <code class="o">}</code> <code class="kd">public</code> <code class="kt">int</code> <code class="nf">getFun</code><code class="o">()</code> <code class="o">{</code> <code class="k">return</code> <code class="n">fun</code><code class="o">;</code> <code class="o">}</code> <code class="o">}</code></pre><p>Here, we’ve added an instance variable, <code class="literal">fun</code>, to the <code class="literal">Weekday</code> class, as well as a constructor and accessor method that work with the value. The declaration of our enum values each now accepts the constructor value, much like a constructor call without the <code class="literal">new</code> keyword. Note that the semicolon at the end of the values is mandatory. Each <code class="literal">Weekday</code> now has a <code class="literal">fun</code> attribute.</p><p>There is an odd special feature of enums that we didn’t show. In addition to adding features to the enum class as a whole (as in our example), we can add methods and variables to individual values of the enumeration by giving them a body with curly braces (<code class="literal">{}</code>). This is best served by an example:</p><a id="I_5_tt284"/><pre class="programlisting"> <code class="kd">enum</code> <code class="n">Cat</code> <code class="o">{</code> <code class="n">Himilayan</code><code class="o">,</code> <code class="n">Siamese</code><code class="o">,</code> <code class="n">Caleco</code><code class="o">,</code> <code class="n">Persian</code> <code class="o">{</code> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">someMethod</code><code class="o">()</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code> <code class="o">}</code> <code class="o">}</code></pre><p>Now, only the <code class="literal">Cat.Persian</code> enum value has the method. In this case, the compiler generates a subclass of <code class="literal">Cat</code> as an inner class of the <code class="literal">Persian</code> type to hold the extra member. (We’ll talk about inner classes in <a class="xref" href="ch06.html" title="Chapter 6. Relationships Among Classes">Chapter 6</a>.) You could use this to have the <code class="literal">Persian</code> member override a method in the base enum class.<a id="I_indexterm5_id693837" class="indexterm"/><a id="I_indexterm5_id693844" class="indexterm"/></p></div></div></body></html>