epubjs
Version:
Render ePub documents in the browser, across many devices
104 lines (96 loc) • 15.8 kB
HTML
<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">></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>