epubjs
Version:
Render ePub documents in the browser, across many devices
30 lines (29 loc) • 6.48 kB
HTML
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Casts</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="Casts"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-8-SECT-5"/>Casts</h1></div></div></div><p><a id="idx10390" class="indexterm"/> <a id="idx10404" class="indexterm"/>We’ve now talked about relationships between generic types
and even between generic types and raw types. But we haven’t brought up
the concept of a cast yet. No cast was necessary when we interchanged
generics with their raw types. Instead, we just crossed a line that
triggers unchecked warnings from the compiler:</p><a id="I_8_tt417"/><pre class="programlisting"> <code class="n">List</code> <code class="n">list</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">List</code><code class="o"><</code><code class="n">Date</code><code class="o">></code> <code class="n">dl</code> <code class="o">=</code> <code class="n">list</code><code class="o">;</code> <code class="c1">// unchecked warning</code></pre><p>Normally, we use a cast in Java to work with two types that could be
assignable. For example, we could attempt to cast an <code class="literal">Object</code> to a <code class="literal">Date</code> because it is plausible that the <code class="literal">Object</code> is a <code class="literal">Date</code> value. The cast then performs the check at
runtime to see if we are correct. Casting between unrelated types is a
compile-time error. For example, we can’t even try to cast an <code class="literal">Integer</code> to a <code class="literal">String</code>. Those types have no inheritance
relationship. What about casts between compatible generic types?</p><a id="I_8_tt418"/><pre class="programlisting"> <code class="n">Collection</code><code class="o"><</code><code class="n">Date</code><code class="o">></code> <code class="n">cd</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">List</code><code class="o"><</code><code class="n">Date</code><code class="o">></code> <code class="n">ld</code> <code class="o">=</code> <code class="o">(</code><code class="n">List</code><code class="o"><</code><code class="n">Date</code><code class="o">>)</code><code class="n">cd</code><code class="o">;</code> <code class="c1">// Ok!</code></pre><p>This code snippet shows a valid cast from a more general <code class="literal">Collection<Date></code> to a <code class="literal">List<Date></code>. The cast is plausible here
because a <code class="literal">Collection<Date></code> is
assignable from and could actually be a <code class="literal">List<Date></code>. Similarly, the following cast
catches our mistake where we have aliased a <code class="literal">TreeSet<Date></code> as a <code class="literal">Collection<Date></code> and tried to cast it to a
<code class="literal">List<Date></code>:</p><a id="I_8_tt419"/><pre class="programlisting"> <code class="n">Collection</code><code class="o"><</code><code class="n">Date</code><code class="o">></code> <code class="n">cd</code> <code class="o">=</code> <code class="k">new</code> <code class="n">TreeSet</code><code class="o"><</code><code class="n">Date</code><code class="o">>();</code>
<code class="n">List</code><code class="o"><</code><code class="n">Date</code><code class="o">></code> <code class="n">ld</code> <code class="o">=</code> <code class="o">(</code><code class="n">List</code><code class="o"><</code><code class="n">Date</code><code class="o">>)</code><code class="n">cd</code><code class="o">;</code> <code class="c1">// Runtime ClassCastException!</code>
<code class="n">ld</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></pre><p>There is one case where casts are not effective with generics,
however, and that is when we are trying to differentiate the types based
on their parameter types:</p><a id="I_8_tt420"/><pre class="programlisting"> <code class="n">Object</code> <code class="n">o</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="n">List</code><code class="o"><</code><code class="n">Date</code><code class="o">></code> <code class="n">ld</code> <code class="o">=</code> <code class="o">(</code><code class="n">List</code><code class="o"><</code><code class="n">Date</code><code class="o">>)</code><code class="n">o</code><code class="o">;</code> <code class="c1">// unchecked warning, ineffective</code>
<code class="n">Date</code> <code class="n">d</code> <code class="o">=</code> <code class="n">ld</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">// unsafe at runtime, implicit cast may fail</code></pre><p>Here, we aliased an <code class="literal">ArrayList<String></code> as a plain <code class="literal">Object</code>. Next, we cast it to a <code class="literal">List<Date></code>. Unfortunately, Java does not
know the difference between a <code class="literal">List<String></code> and a <code class="literal">List<Date></code> at runtime, so the cast is
fruitless. The compiler warns us of this by generating an unchecked
warning at the location of the cast; we should be aware that when we try
to use the cast object later, we might find out that it is incorrect.
Casts on generic types are ineffective at runtime because of erasure and
the lack of type information.<a id="I_indexterm8_id709127" class="indexterm"/><a id="I_indexterm8_id709134" class="indexterm"/></p></div></body></html>