UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

68 lines (66 loc) 9.58 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>Bounds</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="Bounds"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-8-SECT-7"/>Bounds</h1></div></div></div><p><a id="idx10403" class="indexterm"/>In the process of discussing generics, we’ve already had to mention bounds a few times. A bound is a constraint on the type of a type parameter. Bounds use the <a id="I_indexterm8_id710083" class="indexterm"/><code class="literal">extends</code> keyword and some new syntax to limit the parameter types that may be applied to a generic type. In the case of a generic class, the bounds simply limit the type that may be supplied to instantiate it.</p><p>A type variable may extend a class or interface type, meaning that its instantiation must be of that type or a subtype:</p><a id="I_8_tt433"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">EmployeeList</code><code class="o">&lt;</code> <code class="n">T</code> <code class="kd">extends</code> <code class="n">Employee</code> <code class="o">&gt;</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code></pre><p>Here, we made a generic <code class="literal">EmployeeList</code> type that can be instantiated only with <code class="literal">Employee</code> types. We could further require that the <code class="literal">Employee</code> type implement one or more interfaces using the special <a id="I_indexterm8_id710128" class="indexterm"/><a id="I_indexterm8_id710133" class="indexterm"/><code class="literal">&amp;</code> syntax:</p><a id="I_8_tt434"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">EmployeeList</code><code class="o">&lt;</code> <code class="n">T</code> <code class="kd">extends</code> <code class="n">Employee</code> <code class="o">&amp;</code> <code class="n">Ranked</code> <code class="o">&amp;</code> <code class="n">Printable</code> <code class="o">&gt;</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code></pre><p>The order of the <code class="literal">&amp;</code> interface bounds is not significant, but only one class type can be specified and if there is one, it must come first. When a type has no specific bounds, the bound <code class="literal">extends Object</code> is implicit.</p><p>By applying bounds to our type, we not only limit the instantiations of the generic class, but we make the type arguments more useful. Now that we know that our type must extend some type or implement some set of interfaces, we can use variables and arguments declared with <code class="literal">T</code> by those other type names. Here is a somewhat contrived extension of our previous example:</p><a id="I_8_tt435"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">EmployeeList</code><code class="o">&lt;</code> <code class="n">T</code> <code class="kd">extends</code> <code class="n">Employee</code> <code class="o">&amp;</code> <code class="n">Ranked</code> <code class="o">&amp;</code> <code class="n">Printable</code> <code class="o">&gt;</code> <code class="o">{</code> <code class="n">Ranked</code> <code class="n">ranking</code><code class="o">;</code> <code class="n">List</code><code class="o">&lt;</code><code class="n">Printable</code><code class="o">&gt;</code> <code class="n">printList</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o">&lt;</code><code class="n">Printable</code><code class="o">&gt;();</code> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">addEmployee</code><code class="o">(</code> <code class="n">T</code> <code class="n">employee</code> <code class="o">)</code> <code class="o">{</code> <code class="k">this</code><code class="o">.</code><code class="na">ranking</code> <code class="o">=</code> <code class="n">employee</code><code class="o">;</code> <code class="c1">// T as Ranked</code> <code class="n">printList</code><code class="o">.</code><code class="na">add</code><code class="o">(</code> <code class="n">employee</code> <code class="o">);</code> <code class="c1">// T as Printable</code> <code class="o">}</code> <code class="o">}</code></pre><p>This example shows that by placing bounds on the generic parameter type we can require it to be of a particular class type or implement certain interface types. This allows us to use arguments of the parameter type passed to methods in more useful ways. In this example, we know that the <code class="literal">EmployeeList</code> will be instantiated with a generic type that is a <code class="literal">Printable</code> and so we can use the employee argument as a <code class="literal">Printable</code>.</p><p>Type variables can also refer to other type variables within the type declaration:</p><a id="I_8_tt436"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">Foo</code> <code class="o">&lt;</code><code class="n">A</code><code class="o">,</code> <code class="n">B</code> <code class="kd">extends</code> <code class="n">A</code><code class="o">&gt;</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code></pre><p>We’ll see a particularly vicious example of this later when we talk about the definition of the <code class="literal">Enum</code> class. We’ll also see a more convenient technique for declaring how individual elements of a generic class relate to the parameter type when we cover wildcards in the next section.</p><div class="sect2" title="Erasure and Bounds (Working with Legacy Code)"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-8-SECT-7.1"/>Erasure and Bounds (Working with Legacy Code)</h2></div></div></div><p><a id="idx10389" class="indexterm"/> <a id="idx10399" class="indexterm"/> We mentioned earlier in our discussion of erasure that the resulting type used in place of the type parameter in the raw type for the generic class is the bound of the type variable. Specifically, we have seen many generics with no explicit bounds that defaulted to a bound of type <code class="literal">Object</code>. We also showed a quick example of a type that imposed a bound of <code class="literal">extends Date</code> and said that the type of its methods would be <code class="literal">Date</code> instead of <code class="literal">Object</code>. We can now be a little more specific.</p><p><a id="I_indexterm8_id710299" class="indexterm"/>The type after erasure used for the parameter type of a generic class is the <span class="emphasis"><em>leftmost bound</em></span>; that is, the first bound specified after the <code class="literal">extends</code> keyword (literally the leftmost) becomes the type used in the erasure. This implies that if the type extends a class type, it is always the erased type because it must always come first. But if the type extends only interface types, the choice is up to us. This fine point is important for backward compatibility with nongeneric code. Often when creating generic versions of nongeneric APIs, we have the opportunity to “tighten up” the specification a bit. Being aware of the leftmost bound gives us a way to explicitly control the type of the erased class. For example, suppose we create a generic <code class="literal">List</code> class that we only want instantiated on <code class="literal">Listable</code> objects, but we’d prefer not to change the API of our old <code class="literal">List</code> class that accepted <code class="literal">Object</code> type elements. Our initial attempt:</p><a id="I_8_tt437"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">List</code><code class="o">&lt;</code> <code class="n">E</code> <code class="kd">extends</code> <code class="n">Listable</code> <code class="o">&gt;</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code></pre><p>produces a raw type that accepts only <code class="literal">Listable</code>. However, we can insert a somewhat gratuitous additional type, <code class="literal">Object</code>, as the leftmost bound in order to get back our old API without changing the new generic bounds:</p><a id="I_8_tt438"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">List</code><code class="o">&lt;</code> <code class="n">E</code> <code class="kd">extends</code> <code class="n">Object</code> <code class="o">&amp;</code> <code class="n">Listable</code> <code class="o">&gt;</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code></pre><p>Inserting <code class="literal">Object</code> doesn’t change the actual bounds of the generic class but does change the erased signature.<a id="I_indexterm8_id710391" class="indexterm"/><a id="I_indexterm8_id710398" class="indexterm"/><a id="I_indexterm8_id710406" class="indexterm"/></p></div></div></body></html>