epubjs
Version:
Render ePub documents in the browser, across many devices
236 lines (234 loc) • 34.9 kB
HTML
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Wildcards</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="Wildcards"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-8-SECT-8"/>Wildcards</h1></div></div></div><p>We mentioned earlier that the kinds of generic type instantiations
discussed so far in this chapter have all been concrete type
instantiations. We described this as meaning that all of the parameter
arguments are real Java types. For example, <code class="literal">List<String></code> and <code class="literal">List<Date></code> are instantiations of the
generic <code class="literal">List</code> class with the concrete
types <code class="literal">String</code> and <code class="literal">Date</code>. Now we’re going to look at another kind of
generic type instantiation: <span class="emphasis"><em>wildcard
instantiation</em></span>.</p><p>As we’ll see in this section, wildcards are Java’s way of
introducing polymorphism into the type parameter portion of the generic
equation. A wildcard instantiation uses a question mark (<code class="literal">?</code>) in place of an actual type parameter at
instantiation time and denotes that the type can be assigned any of a
range of possible instantiations of the generic type. The <a id="I_indexterm8_id710467" class="indexterm"/><a id="I_indexterm8_id710475" class="indexterm"/><a id="I_indexterm8_id710481" class="indexterm"/><a id="I_indexterm8_id710491" class="indexterm"/><code class="literal">?</code> wildcard by itself is
called the <span class="emphasis"><em>unbounded wildcard</em></span> and denotes that any
type instantiation is acceptable (assignable to the type).</p><a id="I_8_tt439"/><pre class="programlisting"> <code class="n">List</code><code class="o"><?></code> <code class="n">anyInstantiationOfList</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">Date</code><code class="o">>();</code>
<code class="n">anyInstantiationOfList</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">String</code><code class="o">>();</code> <code class="c1">// another instantiation</code></pre><p>In this snippet, we declared a variable <code class="literal">anyInstantiationOfList</code> whose type is the
unbounded wildcard instantiation of the generic <code class="literal">List</code> type. (What a mouthful.) This means that
the type we instantiated can be assigned any particular concrete
instantiation of the <code class="literal">List</code> type, whether
<code class="literal">Date</code>s, <code class="literal">String</code>s, or <code class="literal">Foo</code>s. Here, we assigned it a <code class="literal">List<Date></code> first and, subsequently, a
<code class="literal">List<String></code>.</p><div class="sect2" title="A Supertype of All Instantiations"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-8-SECT-8.1"/>A Supertype of All Instantiations</h2></div></div></div><p><a id="I_indexterm8_id710572" class="indexterm"/> <a id="idx10439" class="indexterm"/>The unbounded wildcard instantiation is a kind of <code class="literal">supertype</code> of all of these concrete
instantiations. In contrast to the generic type relationships that we
saw earlier, which followed only raw, “base” generic types, wildcards
let us implement polymorphism on the parameter types. The unbounded
wildcard is to generic type parameters what the <code class="literal">Object</code> type is to regular Java types: a
supertype of everything.</p><a id="I_8_tt440"/><pre class="programlisting"> <code class="c1">// A List<Object> is not a List<Date>!</code>
<code class="n">List</code><code class="o"><</code><code class="n">Object</code><code class="o">></code> <code class="n">objectList</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">Date</code><code class="o">>()</code> <code class="c1">// Error!</code>
<code class="c1">// A List<?> can be a List<Date></code>
<code class="n">List</code><code class="o"><?></code> <code class="n">anyList</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">Date</code><code class="o">>();</code> <code class="c1">// Yes!</code></pre><p>We are reminded in this example that <code class="literal">List<Object></code> is not a <code class="literal">List<Date></code>; polymorphism doesn’t flow
that way with generic instantiations of concrete types. But <code class="literal">List<?></code>, the unbounded wildcard
instantiation, can be assigned any instantiation of <code class="literal">List</code>. As we go on, we’ll see that wildcards
add a new dimension to the assignability of generic types.<a id="I_indexterm8_id710653" class="indexterm"/></p></div><div class="sect2" title="Bounded Wildcards"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-8-SECT-8.2"/>Bounded Wildcards</h2></div></div></div><p><a id="I_indexterm8_id710667" class="indexterm"/> <a id="idx10420" class="indexterm"/> <a id="I_indexterm8_id710688" class="indexterm"/>A <span class="emphasis"><em>bounded wildcard</em></span> is a wildcard that
uses the <a id="I_indexterm8_id710700" class="indexterm"/><code class="literal">extends</code> keyword just as
a type variable would to limit the range of assignable types. For
example:</p><a id="I_8_tt441"/><pre class="programlisting"> <code class="n">List</code><code class="o"><?</code> <code class="kd">extends</code> <code class="n">Date</code><code class="o">></code> <code class="n">dateInstantiations</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">Date</code><code class="o">>();</code>
<code class="n">dateInstantiations</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">MyDate</code><code class="o">>();</code> <code class="c1">// another instantiation</code></pre><p>Our <code class="literal">dateInstantiations</code> variable
is limited to holding instantiations of <code class="literal">List</code> on parameter types of <code class="literal">Date</code> and its subclasses. So, we can assign it
a <code class="literal">List<Date></code> or a <code class="literal">List<MyDate></code>. In the same way that the
unbounded wildcard serves as a superclass for all instantiations of a
generic type, bounded wildcards create more limited supertypes covering
a narrower range of instantiations. In this case, our wildcard
instantiation, <code class="literal">List<? extends
Date></code>, is the supertype of all instantiations of <code class="literal">List</code> on <code class="literal">Date</code> types. As with type parameter bounds, the
bound <code class="literal">Date</code> is called the upper bound
of the type.</p><p>Wildcard bounds may extend interfaces as well as use the
<a id="I_indexterm8_id710785" class="indexterm"/><a id="I_indexterm8_id710791" class="indexterm"/><code class="literal">&</code> syntax to add
interface requirements to the bound:</p><a id="I_8_tt442"/><pre class="programlisting"> <code class="n">Trap</code><code class="o"><</code> <code class="o">?</code> <code class="kd">extends</code> <code class="n">Catchable</code> <code class="o">&</code> <code class="n">Releaseable</code> <code class="o">></code> <code class="n">trap</code><code class="o">;</code></pre><p>In this case, the instantiation serves as a supertype of the set
of instantiations on types implementing both the <code class="literal">Catchable</code> and <code class="literal">Releaseable</code> interfaces.<a id="I_indexterm8_id710825" class="indexterm"/></p></div><div class="sect2" title="Thinking Outside the Container"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-8-SECT-8.3"/>Thinking Outside the Container</h2></div></div></div><p><a id="idx10422" class="indexterm"/> <a id="idx10440" class="indexterm"/>Let’s be clear about what the wildcard means in the
context of a container type such as <a id="I_indexterm8_id710868" class="indexterm"/><a id="I_indexterm8_id710874" class="indexterm"/><code class="literal">List</code>. The unbounded
wildcard instantiation may be assigned any type instantiation, but it
does ultimately refer to <span class="emphasis"><em>some particular type
instantiation</em></span>. A wildcard instantiation serves as the type of
a variable, and that variable eventually holds some actual concrete
instantiation of the generic type:</p><a id="I_8_tt443"/><pre class="programlisting"> <code class="n">List</code><code class="o"><?></code> <code class="n">someInstantiationOfList</code><code class="o">;</code>
<code class="n">someInstantiationOfList</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">Date</code><code class="o">>();</code>
<code class="n">someInstantiationOfList</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">String</code><code class="o">>();</code></pre><p>In this example, our <code class="literal">List<?></code> variable is either a <code class="literal">List<String></code> or a <code class="literal">List<Date></code>. It is
<span class="emphasis"><em>not</em></span> some new kind of <code class="literal">List</code> that can hold either <code class="literal">String</code> or <code class="literal">Date</code> elements.</p><p>In the same way, a wildcard with bounds ultimately holds one of
the concrete instantiations assignable to its bounds. Imagine for a
moment that we have a private class <code class="literal">Foo</code> with only one subclass <code class="literal">Bar</code> and no others. The expression <code class="literal">Collection<? extends Foo></code> in this case
means the set of two possibilities: either <code class="literal">Collection<Foo></code> or <code class="literal">Collection<Bar></code>—that is, either a
<code class="literal">Collection</code> of elements with a common
supertype of <code class="literal">Foo</code> or a collection of
elements with a common supertype of <code class="literal">Bar</code>. Again, the wildcard instantiation matches
either of those generic type instantiations. It does
<span class="emphasis"><em>not</em></span> create a new type of collection that can
contain either <code class="literal">Foo</code>s or <code class="literal">Bar</code>s. (That is actually the job of <code class="literal">Collection<Foo></code>, which can contain both
<code class="literal">Foo</code> and <code class="literal">Bar</code> elements.)</p><p>For this reason, wildcard type instantiations are valid types for
referencing an object, but they cannot be used as the type to create an
instance of an object. In general, you cannot use a wildcard type with
the <code class="literal">new</code> keyword to allocate an object
instance because the wildcard denotes one or a possible set of objects.
It doesn’t make sense.<a id="I_indexterm8_id711033" class="indexterm"/><a id="I_indexterm8_id711040" class="indexterm"/></p></div><div class="sect2" title="Lower Bounds"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-8-SECT-8.4"/>Lower Bounds</h2></div></div></div><p><a id="idx10421" class="indexterm"/> <a id="idx10438" class="indexterm"/>We saw the <code class="literal">extends</code>
construct used to specify an upper bound for both type variables and
wildcard instantiations. It implies a type that is “at the top” of the
object hierarchy for the bound. Wildcard instantiations actually allow
another type of bound called a <span class="emphasis"><em>lower bound</em></span> as well.
A lower bound is specified with the keyword <a id="I_indexterm8_id711094" class="indexterm"/><code class="literal">super</code> and, as you might
guess, requires that instantiations be of a certain type or any of its
supertypes, up to <code class="literal">Object</code>. For
example:</p><a id="I_8_tt444"/><pre class="programlisting"> <code class="n">List</code><code class="o"><</code> <code class="o">?</code> <code class="kd">super</code> <code class="n">MyDate</code> <code class="o">></code> <code class="n">listOfAssignableFromMyDate</code><code class="o">;</code>
<code class="n">listOfAssignableFromMyDate</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">MyDate</code><code class="o">>();</code>
<code class="n">listOfAssignableFromMyDate</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">Date</code><code class="o">>();</code>
<code class="n">listOfAssignableFromMyDate</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">Object</code><code class="o">>();</code></pre><p>This wildcard instantiation creates a type that can hold any
instantiation of <code class="literal">List</code> on the type
<code class="literal">MyDate</code> or any of its supertypes. In
our example world, that means the wildcard type can be assigned one of
only three types: <code class="literal">List<MyDate></code>,
<code class="literal">List<Date></code>, or <code class="literal">List<Object></code>. Here, we have cut off the
object inheritance hierarchy after three generations. No further
subclasses of <code class="literal">MyDate</code> can be
used.</p><p>As we hinted in the example, it may help to read <code class="literal">? super MyDate</code> as “Assignable from MyDate.”
Lower bounds are useful for cases where we want to be sure that a
particular container instantiation can hold a particular element type,
without limiting it to just the specific type of the element. We’ll show
a good example of this when we talk about generic methods later. For
now, just try to digest this as complementary to upper bounds.</p><p>One last thing about lower bounds: only the wildcard instantiation
syntax can use the <code class="literal">super</code> keyword to
refer to lower bounds. Bounds of type variables in generic class
declarations cannot have lower bounds. Erasure replaces all references
to the type variables with their upper bounds, so runtime types have no
way to enforce the contract.<a id="I_indexterm8_id711188" class="indexterm"/><a id="I_indexterm8_id711195" class="indexterm"/></p></div><div class="sect2" title="Reading, Writing, and Arithmetic"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-8-SECT-8.5"/>Reading, Writing, and Arithmetic</h2></div></div></div><p><a id="idx10423" class="indexterm"/> <a id="idx10442" class="indexterm"/>We’ve glossed over an important issue so far in our
discussion of wildcard types: namely, how can we use them? What kinds of
types does the compiler enforce for variables and arguments that
referred to the type variables in the generic class? For example, if we
have a <code class="literal">List<?></code> list of any
instantiation type, what are the rules about putting objects into it and
getting them back out? What is their type?</p><p>We have to take the two cases separately. Drawing on the analogy
of a container, we’ll call getting a return value from a method on an
object as a specific type <span class="emphasis"><em>reading the object as a
type</em></span>. Conversely, we’ll call passing arguments of a specific
type to methods of the object <span class="emphasis"><em>writing the object as a
type</em></span>. So, for example, a <code class="literal">List<Date></code> can be read and written as
the <code class="literal">Date</code> type and a <code class="literal">Trap<Mouse></code> has methods that can be read
and written as the <code class="literal">Mouse</code> type.</p><p>To be more precise, though, we should say that <code class="literal">List<Date></code> can be read as the <code class="literal">Date</code> type, but can be written as any subtype
of <code class="literal">Date</code>. After all, we could add a
<code class="literal">MyDate</code> to a <code class="literal">List<Date></code>. Let’s look now at the
wildcard instantiation <code class="literal">List< ? extends Date
></code>. We know it holds an instantiation of the <code class="literal">List</code> type on some type of <code class="literal">Date</code>. What more can we say about the elements
of such a <code class="literal">List</code>, which could hold
<span class="emphasis"><em>any</em></span> instantiation of the <code class="literal">Date</code> type? Well, the elements will always be
subtypes of <code class="literal">Date</code>. This means that at
a minimum, we should be able to read the object through our wildcard
type as type <code class="literal">Date</code>:</p><a id="I_8_tt445"/><pre class="programlisting"> <code class="n">List</code><code class="o"><</code> <code class="o">?</code> <code class="kd">extends</code> <code class="n">Date</code> <code class="o">></code> <code class="n">someDateList</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">MyDate</code><code class="o">>();</code>
<code class="o">...</code>
<code class="n">Date</code> <code class="n">date</code> <code class="o">=</code> <code class="n">someDateList</code><code class="o">.</code><code class="na">get</code><code class="o">(</code> <code class="mi">0</code> <code class="o">);</code> <code class="c1">// read as Date</code></pre><p>The compiler lets us assign the value directly to a <code class="literal">Date</code> because it knows that whatever the
instantiation of the <code class="literal">List</code>, the
elements must be a subtype of <code class="literal">Date</code>.
(Of course, we could have read the object as type <code class="literal">Object</code> or any supertype of <code class="literal">Date</code> if we’d wanted to as well.)</p><p>But what about going the other way and writing? If <code class="literal">someDatelist</code> could be an instantiation of
<code class="literal">List</code> on any subclass of <code class="literal">Date</code>, how can we know what type of objects to
write to it? (How can we safely call its <code class="literal">add()</code> method?) The answer is that we can’t.
Since we don’t know the correct type, the compiler won’t let us write
anything to the <code class="literal">List</code> through our
wildcard instantiation of the type:</p><a id="I_8_tt446"/><pre class="programlisting"> <code class="n">List</code><code class="o"><</code> <code class="o">?</code> <code class="kd">extends</code> <code class="n">Date</code> <code class="o">></code> <code class="n">someDateList</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">MyDate</code><code class="o">>();</code>
<code class="n">someDatelist</code><code class="o">.</code><code class="na">add</code><code class="o">(</code> <code class="k">new</code> <code class="n">Date</code><code class="o">()</code> <code class="o">);</code> <code class="c1">// Compile-time Error!</code>
<code class="n">someDatelist</code><code class="o">.</code><code class="na">add</code><code class="o">(</code> <code class="k">new</code> <code class="n">MyDate</code><code class="o">()</code> <code class="o">);</code> <code class="c1">// Compile-time Error!</code></pre><p>Another way to put this is that because our wildcard instantiation
has an upper bound of <code class="literal">Date</code>, we can
only <span class="emphasis"><em>read </em></span>the type as <code class="literal">Date</code>. We’ll reiterate that in the form of a
rule in a moment.</p><p>Recall that an unbounded wildcard is really just a wildcard with a
bound of type <code class="literal">Object <? extends
Object></code>. Obviously, even an unbounded wildcard
instantiation holds objects that can be assigned to <code class="literal">Object</code>, so it’s OK to read an unbounded
wildcard as the <code class="literal">Object</code> type:</p><a id="I_8_tt447"/><pre class="programlisting"> <code class="n">List</code><code class="o"><?></code> <code class="n">someList</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">String</code><code class="o">>();</code>
<code class="o">...</code>
<code class="n">Object</code> <code class="n">object</code> <code class="o">=</code> <code class="n">someList</code><code class="o">.</code><code class="na">get</code><code class="o">(</code> <code class="mi">0</code> <code class="o">);</code> <code class="c1">// read as Object</code></pre><p>But, of course, we cannot know the actual type of the elements, so
we cannot write to the list through our unbounded wildcard type.</p><p>What about lower bounds? Well, the situation is neatly reversed
with respect to reading and writing. Because we know that the elements
of any instantiation matching our lower bounded wildcard must be a
supertype of the lower bound, we can write to the object as the lower
bound type through our wildcard:</p><a id="I_8_tt448"/><pre class="programlisting"> <code class="n">List</code><code class="o"><</code> <code class="o">?</code> <code class="kd">super</code> <code class="n">MyDate</code> <code class="o">></code> <code class="n">listAssignableMyDate</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">Date</code><code class="o">>();</code>
<code class="n">listAssignableMyDate</code><code class="o">.</code><code class="na">add</code><code class="o">(</code> <code class="k">new</code> <code class="n">MyDate</code><code class="o">()</code> <code class="o">);</code>
<code class="n">listAssignableMyDate</code><code class="o">.</code><code class="na">add</code><code class="o">(</code> <code class="k">new</code> <code class="n">Date</code><code class="o">()</code> <code class="o">);</code> <code class="c1">// Compile-time Error!</code></pre><p>But because we do not know what supertype of <code class="literal">MyDate</code> the elements are, we cannot read the
list as any specific type. Of course, the <code class="literal">List</code> must still hold some type of <code class="literal">Object</code>, so we can always read the lower
bounded list as type <code class="literal">Object</code> through
the wildcard. The type <code class="literal">Object</code> is the
default upper bound:</p><a id="I_8_tt449"/><pre class="programlisting"> <code class="n">Object</code> <code class="n">obj</code> <code class="o">=</code> <code class="n">listAssignableMyDate</code><code class="o">.</code><code class="na">get</code><code class="o">(</code> <code class="mi">0</code> <code class="o">);</code> <code class="c1">// read as Object</code></pre><p>Whew. Well, having gone through that explanation, we can now sum
it up concisely in an easy-to-remember rule:</p><div class="blockquote"><blockquote class="blockquote"><p>Wildcard instantiations of generic types can be read as their
upper bound and written as their lower bound.</p></blockquote></div><p>To elaborate: all wildcard instantiations have an upper bound of
<code class="literal">Object</code> even if none other is
specified, so all wildcard instantiations can at least be read as type
<code class="literal">Object</code>. But not all wildcards have a
lower bound. Only those using the <code class="literal">super</code> construct have a lower bound and so only
those wildcard instantiations can be written as a type more specific
than <code class="literal">Object</code>.<a id="I_indexterm8_id711591" class="indexterm"/><a id="I_indexterm8_id711598" class="indexterm"/></p></div><div class="sect2" title="<?>, <Object>, and the Raw Type"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-8-SECT-8.6"/><?>, <Object>, and the Raw Type</h2></div></div></div><p><a id="I_indexterm8_id711613" class="indexterm"/> <a id="I_indexterm8_id711619" class="indexterm"/> <a id="I_indexterm8_id711628" class="indexterm"/> <a id="I_indexterm8_id711639" class="indexterm"/> <a id="I_indexterm8_id711650" class="indexterm"/> <a id="I_indexterm8_id711660" class="indexterm"/>We’ve covered a lot of ground and the semantics can be a
bit hard to follow. Let’s exercise our knowledge by reviewing a few
cases that may or may not have similarities.</p><p>Natural questions to ask are, What good is the unbounded wildcard
anyway? Why not just use the raw type? How do unbounded wildcard
instantiation and raw types compare? The first difference is that the
compiler will issue unchecked warnings when we use methods of the raw
type. But that’s superficial. Why is the compiler warning us? It’s
because it cannot stop us from abusing our raw type by foisting the
wrong type of objects on it. Using an unbounded wildcard is like putting
on boxing gloves and saying that we want to play by the rules. Doing so
comes at a cost. The compiler guarantees that we are safe by allowing us
only the operations that it knows are safe—namely, reading as type
<code class="literal">Object</code> (the upper bound of
everything). The compiler does not let us write to an unbounded wildcard
at all. So why use the unbounded wildcard? To play by the rules of
generics and guarantee that we don’t do anything unsafe.</p><p>Next, we can knock down any notion that an unbounded wildcard
instantiation is similar to an instantiation on the type <code class="literal">Object</code>. Remember that a <a id="I_indexterm8_id711702" class="indexterm"/><a id="I_indexterm8_id711708" class="indexterm"/><code class="literal">List<?></code> holds
<span class="emphasis"><em>some</em></span> instantiation of <code class="literal">List</code>. It could be a <code class="literal">List<Date></code> for all we know. But a
<code class="literal">List<Object></code> is actually a list
that holds concrete <code class="literal">Object</code> types. The
<code class="literal">List<Object></code> can be read and
written as <code class="literal">Object</code>. The <code class="literal">List<?></code> can only be read (not written)
and only read as <code class="literal">Object</code> in a
degenerate sense. The elements of <code class="literal">List<?></code> are actually all of some unknown
type. The elements of the unknown type list all have a common supertype
that could be <code class="literal">Object</code> or some other
common type that is more restrictive than <code class="literal">Object</code>. The knowledge of what “could be” in
the <code class="literal">List<?></code> doesn’t do much for
us in practice, but means something completely different from <code class="literal">List<Object></code>.</p><p>Finally, let’s round out the comparisons by asking how <code class="literal">List<Object></code> and the raw type compare.
Now we’re onto something. In fact, the raw type after erasure
<span class="emphasis"><em>is</em></span> effectively <code class="literal">List<Object></code> as you’ll recall. But in
this case, we’re telling the compiler that this is OK. Here, we are
asking for a type with elements that can hold any type safely and the
compiler obliges. The answer to the question of how <code class="literal">List<Object></code> and the raw type <code class="literal">List</code> compare is that <code class="literal">List<Object></code> is the “generic safe”
version of the raw type of yesterday.</p></div><div class="sect2" title="Wildcard Type Relationships"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-8-SECT-8.7"/>Wildcard Type Relationships</h2></div></div></div><p><a id="idx10424" class="indexterm"/> <a id="idx10441" class="indexterm"/>Before we leave our wild discussion of wildcard types,
let’s return one more time to the notion of wildcard type instantiations
as types in the Java type system. Earlier in this chapter, we described
how regular concrete instantiations of generic types are related by
virtue of their “base” generic type inheritance, only with the proviso
that their type parameters are exactly the same. Later, we tried to
instill the idea that wildcard instantiations add an inheritance
relationship to the type parameters, which is the other half of the
generic instantiation. Now, we’ll bring the two together. Things can get
arcane pretty quickly, but the simple cases are easy to swallow.</p><p>The question is, if we have two different wildcard instantiations
of a type or related types, how, if at all, are they related? For
example, can an unbounded wildcard be assigned a value with a more
restrictive bound because it can hold any instantiation?</p><a id="I_8_tt450"/><pre class="programlisting"> <code class="n">List</code><code class="o"><</code> <code class="o">?</code> <code class="kd">extends</code> <code class="n">Date</code> <code class="o">></code> <code class="n">dateLists</code> <code class="o">=</code> <code class="o">...;</code>
<code class="n">List</code><code class="o"><</code> <code class="o">?</code> <code class="o">></code> <code class="n">anylists</code><code class="o">;</code>
<code class="n">anyLists</code> <code class="o">=</code> <code class="n">dateLists</code><code class="o">;</code> <code class="c1">// Ok!</code></pre><p>The answer is yes. For purposes of assignability, wildcard
instantiations can be considered as types with possible supertype or
subtype relationships determined by their bounds. Let’s spell out the
unbounded wildcard instantiation as it really is, an instantiation with
an upper bound of <code class="literal">Object</code>:</p><a id="I_8_tt451"/><pre class="programlisting"> <code class="n">List</code><code class="o"><</code> <code class="o">?</code> <code class="kd">extends</code> <code class="n">Date</code> <code class="o">></code> <code class="n">dateLists</code> <code class="o">=</code> <code class="o">...;</code>
<code class="n">List</code><code class="o"><</code> <code class="o">?</code> <code class="kd">extends</code> <code class="n">Object</code> <code class="o">></code> <code class="n">objectLists</code><code class="o">;</code>
<code class="n">objectLists</code> <code class="o">=</code> <code class="n">dateLists</code><code class="o">;</code> <code class="c1">// Ok!</code></pre><p>The rule is that if the “base” generic, raw type is assignable and
the bounds of the wildcard instantiation are also assignable, the
overall types are assignable. Let’s look at another example:</p><a id="I_8_tt452"/><pre class="programlisting"> <code class="n">List</code><code class="o"><</code> <code class="o">?</code> <code class="kd">extends</code> <code class="n">Integer</code> <code class="o">></code> <code class="n">intLists</code> <code class="o">=</code> <code class="o">...;</code>
<code class="n">Collection</code><code class="o"><</code> <code class="o">?</code> <code class="kd">extends</code> <code class="n">Number</code> <code class="o">></code> <code class="n">numCollections</code><code class="o">;</code>
<code class="n">numCollections</code> <code class="o">=</code> <code class="n">intLists</code><code class="o">;</code> <code class="c1">// Ok!</code></pre><p>What this effectively says is that some <code class="literal">List</code> of <code class="literal">Integer</code> types can be treated as some <code class="literal">Collection</code> of <code class="literal">Number</code> types through the wildcard
instantiation. If you think about it, you’ll see that there is no
conflict here. A <code class="literal">List</code> is certainly a
<code class="literal">Collection</code>. And all we’re doing is
widening the type by which we can read the elements from <code class="literal">Integer</code> to <code class="literal">Number</code>. In neither case could we have written
to the collection via the wildcard instantiation anyway.</p><p>What all this ultimately means is that with the introduction of
wildcard instantiations, the type relationships of Java generic classes
become two-dimensional. There is the raw type relationship to consider
and then the wildcard parameter relationship. In fact, if you consider
that generic classes may have more than one type parameter, the
relationships can get even more complicated
(<span class="emphasis"><em>N</em></span>-dimensional). Fortunately, none of this comes up
very often in the real world.<a id="I_indexterm8_id712007" class="indexterm"/><a id="I_indexterm8_id712014" class="indexterm"/></p></div></div></body></html>