epubjs
Version:
Render ePub documents in the browser, across many devices
87 lines (83 loc) • 11.9 kB
HTML
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>The Class Class</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="The Class Class"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-7-SECT-2"/>The Class Class</h1></div></div></div><p><a id="idx10353" class="indexterm"/> <a id="idx10372" class="indexterm"/>A good measure of the complexity of an object-oriented
language is the degree of abstraction of its class structures. We know
that every object in Java is an instance of a class, but what exactly is a
class? In languages like traditional C++, objects are formulated by and
instantiated from classes, but classes are really just artifacts of the
compiler. In those languages, you see classes mentioned only in source
code, not at runtime. By comparison, classes in Smalltalk are real,
runtime entities in the language that are themselves described by
“metaclasses” and “metaclass classes.” Java strikes a happy medium between
these two languages with what is effectively a two-tiered system that uses
<code class="literal">Class</code> objects.</p><p>Classes in Java source code are represented at runtime by instances
of the <code class="literal">java.lang.Class</code> class. There’s a
<code class="literal">Class</code> object for every object type you
use; this <code class="literal">Class</code> object is responsible
for producing instances of that type. But you don’t generally have to
worry about that unless you are interested in loading new kinds of classes
dynamically at runtime or using a highly abstracted API that wants a
“type” instead of an actual argument. The <code class="literal">Class</code> object is also the basis for “reflecting”
on a class to find its methods and other properties, allowing you to find
out about an object’s structure or invoke its methods programmatically at
runtime. We’ll discuss reflection in the next section.</p><p>We get the <code class="literal">Class</code> associated with
a particular object with the <a id="I_indexterm7_id703080" class="indexterm"/><code class="literal">getClass()</code> method:</p><a id="I_7_tt367"/><pre class="programlisting"> <code class="n">String</code> <code class="n">myString</code> <code class="o">=</code> <code class="s">"Foo!"</code>
<code class="n">Class</code> <code class="n">stringClass</code> <code class="o">=</code> <code class="n">myString</code><code class="o">.</code><code class="na">getClass</code><code class="o">();</code></pre><p>We can also get the <code class="literal">Class</code>
reference for a particular class statically, using the <a id="I_indexterm7_id703108" class="indexterm"/><code class="literal">.class</code> notation:</p><a id="I_7_tt368"/><pre class="programlisting"> <code class="n">Class</code> <code class="n">stringClass</code> <code class="o">=</code> <code class="n">String</code><code class="o">.</code><code class="na">class</code><code class="o">;</code></pre><p>The <code class="literal">.class</code> reference looks like a
static field that exists in every class. However, it is really resolved by
the compiler.</p><p>One thing we can do with the <code class="literal">Class</code> object is ask for its full name:</p><a id="I_7_tt369"/><pre class="programlisting"> <code class="n">String</code> <code class="n">s</code> <code class="o">=</code> <code class="s">"Boofa!"</code><code class="o">;</code>
<code class="n">Class</code> <code class="n">stringClass</code> <code class="o">=</code> <code class="n">s</code><code class="o">.</code><code class="na">getClass</code><code class="o">();</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code> <code class="n">stringClass</code><code class="o">.</code><code class="na">getName</code><code class="o">()</code> <code class="o">);</code> <code class="c1">// "java.lang.String"</code></pre><p>Another thing that we can do with a <code class="literal">Class</code> is to ask it to produce a new instance of
its type of object. Continuing with the previous example:</p><a id="I_7_tt370"/><pre class="programlisting"> <code class="k">try</code> <code class="o">{</code>
<code class="n">String</code> <code class="n">s2</code> <code class="o">=</code> <code class="o">(</code><code class="n">String</code><code class="o">)</code><code class="n">stringClass</code><code class="o">.</code><code class="na">newInstance</code><code class="o">();</code>
<code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code> <code class="n">InstantiationException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code> <code class="n">IllegalAccessException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code></pre><p>Here, <a id="I_indexterm7_id703173" class="indexterm"/><code class="literal">newInstance()</code> has a
return type of <code class="literal">Object</code>, so we have to
cast it to a reference of the appropriate type. This is fine, but we’ll
see in the next chapter that the <code class="literal">Class</code>
class is a generic class, which means that we can parameterize it to be
more specific about the Java type we’re dealing with; that is, we can get
the <code class="literal">newInstance()</code> method to return the
correct type directly without the cast. We’ll show this here, but don’t
worry if it doesn’t make any sense yet:</p><a id="I_7_tt371"/><pre class="programlisting"> <code class="n">Class</code><code class="o"><</code><code class="n">String</code><code class="o">></code> <code class="n">stringClass</code> <code class="o">=</code> <code class="n">String</code><code class="o">.</code><code class="na">class</code><code class="o">;</code>
<code class="k">try</code> <code class="o">{</code>
<code class="n">String</code> <code class="n">s2</code> <code class="o">=</code> <code class="n">stringClass</code><code class="o">.</code><code class="na">newInstance</code><code class="o">();</code> <code class="c1">// no cast necessary</code>
<code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code> <code class="n">InstantiationException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code> <code class="n">IllegalAccessException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code></pre><p>A couple of exceptions can be thrown here. An <a id="I_indexterm7_id703222" class="indexterm"/><code class="literal">InstantiationException</code>
indicates that we’re trying to instantiate an <code class="literal">abstract</code> class or an interface. <a id="I_indexterm7_id703240" class="indexterm"/><code class="literal">IllegalAccessException</code> is
a more general exception that indicates that we can’t access a constructor
for the object. Note that <code class="literal">newInstance()</code>
can create only an instance of a class that has an accessible default
constructor. It doesn’t allow us to pass any arguments to a constructor.
(In the next section, we’ll learn how to do just that using the Reflection
API.)</p><p>All of this becomes more meaningful when we add the capability to
look up a class by name. <code class="literal">forName()</code> is a
<code class="literal">static</code> method of <code class="literal">Class</code> that returns a <code class="literal">Class</code> object given its name as a <code class="literal">String</code>:</p><a id="I_7_tt372"/><pre class="programlisting"> <code class="k">try</code> <code class="o">{</code>
<code class="n">Class</code> <code class="n">sneakersClass</code> <code class="o">=</code> <code class="n">Class</code><code class="o">.</code><code class="na">forName</code><code class="o">(</code><code class="s">"Sneakers"</code><code class="o">);</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">ClassNotFoundException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code></pre><p>A <a id="I_indexterm7_id703303" class="indexterm"/><code class="literal">ClassNotFoundException</code> is
thrown if the class can’t be located.</p><p>Combining these tools, we have the power to load new kinds of
classes dynamically. When combined with the power of interfaces, we can
use new data types loaded by a string name in our applications:</p><a id="I_7_tt373"/><pre class="programlisting"> <code class="kd">interface</code> <code class="nc">Typewriter</code> <code class="o">{</code>
<code class="kt">void</code> <code class="nf">typeLine</code><code class="o">(</code> <code class="n">String</code> <code class="n">s</code> <code class="o">);</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="kd">class</code> <code class="nc">Printer</code> <code class="kd">implements</code> <code class="n">Typewriter</code> <code class="o">{</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="kd">class</code> <code class="nc">MyApplication</code> <code class="o">{</code>
<code class="o">...</code>
<code class="n">String</code> <code class="n">outputDeviceName</code> <code class="o">=</code> <code class="s">"Printer"</code><code class="o">;</code>
<code class="k">try</code> <code class="o">{</code>
<code class="n">Class</code> <code class="n">newClass</code> <code class="o">=</code> <code class="n">Class</code><code class="o">.</code><code class="na">forName</code><code class="o">(</code> <code class="n">outputDeviceName</code> <code class="o">);</code>
<code class="n">Typewriter</code> <code class="n">device</code> <code class="o">=</code> <code class="o">(</code><code class="n">Typewriter</code><code class="o">)</code><code class="n">newClass</code><code class="o">.</code><code class="na">newInstance</code><code class="o">();</code>
<code class="o">...</code>
<code class="n">device</code><code class="o">.</code><code class="na">typeLine</code><code class="o">(</code><code class="s">"Hello..."</code><code class="o">);</code>
<code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code> <code class="n">Exception</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code>
<code class="o">}</code></pre><p>Here, we have an application loading a class implementation
(<code class="literal">Printer</code>, which implements the <code class="literal">Typewriter</code> interface) knowing only its name.
Imagine the name was entered by the user or looked up from a configuration
file. This kind of class loading is the basis for many kinds of
configurable systems in Java.<a id="I_indexterm7_id703347" class="indexterm"/><a id="I_indexterm7_id703354" class="indexterm"/></p></div></body></html>