epubjs
Version:
Render ePub documents in the browser, across many devices
364 lines (355 loc) • 57.2 kB
HTML
<?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>Reflection</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="Reflection"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-7-SECT-3"/>Reflection</h1></div></div></div><p>In this section, we’ll take a look at the Java Reflection API,
supported by the classes in the <a id="I_indexterm7_id703370" class="indexterm"/><code class="literal">java.lang.reflect</code>
package. As its name suggests, reflection is the ability for a class or
object to examine itself. Reflection lets Java code look at an object
(more precisely, the class of the object) and determine its structure.
Within the limits imposed by the security manager, you can find out what
constructors, methods, and fields a class has, as well as their
attributes. You can even change the value of fields, dynamically invoke
methods, and construct new objects, much as if Java had primitive pointers
to variables and methods. And you can do all this on objects that your
code has never even seen before. The Annotations API also has the ability
to preserve metadata about source code in the compiled classes and we can
retrieve this information with the Reflection API.</p><p>We don’t have room here to cover the Reflection API fully. As you
might expect, the <code class="literal">reflect</code> package is
complex and rich in details. But reflection has been designed so that you
can do a lot with relatively little effort; 20% of the effort gives you
80% of the fun.</p><p>The Reflection API can be used to determine the capabilities of
objects at runtime. It’s used by object serialization to tear apart and
build objects for transport over streams or into persistent storage.
Obviously, the power to pick apart objects and see their internals must be
zealously guarded by the security manager. The general rule is that your
code is not allowed to do anything with the Reflection API that it
couldn’t do with static (ordinary, compiled) Java code. In short,
reflection is a powerful tool, but it isn’t an automatic loophole. By
default, an object can’t use it to work with fields or methods that it
wouldn’t normally be able to access (for example, another object’s private
fields), although those privileges can be granted, as we’ll discuss
later.</p><p>The three primary features of a class are its fields (variables),
methods, and constructors. For purposes of describing and accessing an
object, these three features are represented by separate classes in the
Reflection API: <a id="I_indexterm7_id703421" class="indexterm"/><code class="literal">java.lang.reflect.Field</code>,
<a id="I_indexterm7_id703432" class="indexterm"/><code class="literal">java.lang.reflect.Method</code>
, and <a id="I_indexterm7_id703442" class="indexterm"/><code class="literal">java.lang.reflect.Constructor</code> . We can look up
these members of a class through the <code class="literal">Class</code> object.</p><p>The <code class="literal">Class</code> class provides two
pairs of methods for getting at each type of feature. One pair allows
access to a class’s public features (including those inherited from its
superclasses) while the other pair allows access to any public or
nonpublic item declared directly within the class (but not features that
are inherited), subject to security considerations. Some examples:</p><div class="itemizedlist"><ul class="itemizedlist"><li class="listitem"><p><a id="I_indexterm7_id703477" class="indexterm"/> <code class="literal">getFields()</code> returns
an array of <code class="literal">Field</code> objects
representing all a class’s public variables, including those it
inherits.</p></li><li class="listitem"><p><a id="I_indexterm7_id703498" class="indexterm"/> <code class="literal">getDeclaredFields()</code>
returns an array representing all the variables declared in the class,
regardless of their access modifiers, but not including inherited
variables.</p></li><li class="listitem"><p>For constructors, the distinction between “all constructors” and
“declared constructors” is not meaningful (classes do not inherit
constructors), so <a id="I_indexterm7_id703518" class="indexterm"/><code class="literal">getConstructors()</code> and
<a id="I_indexterm7_id703529" class="indexterm"/><code class="literal">getDeclaredConstructors()</code> differ only in
that the former returns public constructors while the latter returns
all the class’s constructors.</p></li></ul></div><p>Each set of methods includes the methods for listing all the items
at once (for example, <code class="literal">getFields()</code>) and
an additional method for looking up a particular item by name and—for methods and constructors—by
signature (for example, <code class="literal">getField()</code>,
which takes the field name as an argument).</p><p>The following listing shows the methods in the <code class="literal">Class</code> class:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">Field [] getFields();</code></span></dt><dd><p><a id="I_indexterm7_id703582" class="indexterm"/>Get all public variables, including inherited
ones.</p></dd><dt><span class="term"><code class="literal">Field getField(String
name);</code></span></dt><dd><p><a id="I_indexterm7_id703598" class="indexterm"/>Get the specified public variable, which may be
inherited.</p></dd><dt><span class="term"><code class="literal">Field []
getDeclaredFields();</code></span></dt><dd><p><a id="I_indexterm7_id703614" class="indexterm"/>Get all public and nonpublic variables declared in
this class (not including those inherited from superclasses).</p></dd><dt><span class="term"><code class="literal">Field getDeclaredField(String
name);</code></span></dt><dd><p><a id="I_indexterm7_id703630" class="indexterm"/>Get the specified variable, public or nonpublic,
declared in this class (inherited variables not considered).</p></dd><dt><span class="term"><code class="literal">Method []
getMethods();</code></span></dt><dd><p><a id="I_indexterm7_id703647" class="indexterm"/>Get all public methods, including inherited
ones.</p></dd><dt><span class="term"><code class="literal">Method getMethod(String name, Class ...
argumentTypes);</code></span></dt><dd><p><a id="I_indexterm7_id703663" class="indexterm"/>Get the specified public method that has arguments
that match the types listed in <code class="literal">argumentTypes</code>. The method may be
inherited.</p></dd><dt><span class="term"><code class="literal">Method []
getDeclaredMethods();</code></span></dt><dd><p><a id="I_indexterm7_id703685" class="indexterm"/>Get all public and nonpublic methods declared in this
class (not including those inherited from superclasses).</p></dd><dt><span class="term"><code class="literal">Method getDeclaredMethod(String name,
Class ... argumentTypes);</code></span></dt><dd><p><a id="I_indexterm7_id703702" class="indexterm"/>Get the specified method, public or nonpublic, that
has arguments that match the types listed in <code class="literal">argumentTypes</code>, and which is declared in
this class (inherited methods not considered).</p></dd><dt><span class="term"><code class="literal">Constructor []
getConstructors();</code></span></dt><dd><p><a id="I_indexterm7_id703725" class="indexterm"/>Get all public constructors of this class.</p></dd><dt><span class="term"><code class="literal">Constructor getConstructor(Class ...
argumentTypes);</code></span></dt><dd><p><a id="I_indexterm7_id703741" class="indexterm"/>Get the specified public constructor of this class
that has arguments that match the types listed in <code class="literal">argumentTypes</code>.</p></dd><dt><span class="term"><code class="literal">Constructor []
getDeclaredConstructors();</code></span></dt><dd><p><a id="I_indexterm7_id703763" class="indexterm"/>Get all public and nonpublic constructors of this
class.</p></dd><dt><span class="term"><code class="literal">Constructor
getDeclaredConstructor(Class ... argumentTypes);</code></span></dt><dd><p><a id="I_indexterm7_id703779" class="indexterm"/>Get the specified constructor, public or nonpublic,
that has arguments that match the types listed in <code class="literal">argumentTypes</code>.</p></dd><dt><span class="term"><code class="literal">Class []
getDeclaredClasses();</code></span></dt><dd><p><a id="I_indexterm7_id703801" class="indexterm"/>Get all public and nonpublic inner classes declared
within this class.</p></dd><dt><span class="term"><code class="literal">Constructor []
getInterfaces();</code></span></dt><dd><p><a id="I_indexterm7_id703817" class="indexterm"/>Get all interfaces implemented by this class, in the
order in which they are declared.</p></dd></dl></div><p>As you can see, the four <code class="literal">getMethod()</code> and <code class="literal">getConstructor()</code> methods take advantage of the
Java variable-length argument lists to allow you to pass in the argument
types. In older versions of Java, you have to pass an array of <code class="literal">Class</code> types in their place. We’ll show an
example later.</p><p>As a quick example, we’ll show how easy it is to list all the public
methods of the <code class="literal">java.util.Calendar</code>
class:</p><a id="I_7_tt374"/><pre class="programlisting"> <code class="k">for</code> <code class="o">(</code> <code class="n">Method</code> <code class="n">method</code> <code class="o">:</code> <code class="n">Calendar</code><code class="o">.</code><code class="na">class</code><code class="o">.</code><code class="na">getMethods</code><code class="o">()</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">method</code> <code class="o">);</code></pre><p>Here, we’ve used the <a id="I_indexterm7_id703867" class="indexterm"/><code class="literal">.class</code> notation to get a
reference to the <code class="literal">Class</code> of <code class="literal">Calendar</code>. Remember the discussion of the
<code class="literal">Class</code> class; the reflection methods
don’t belong to a particular instance of <code class="literal">Calendar</code> itself; they belong to the <code class="literal">java.lang.Class</code> object that describes the
<code class="literal">Calendar</code> class. If we wanted to start
from an instance of <code class="literal">Calendar</code> (or, say,
an unknown object), we could have used the <a id="I_indexterm7_id703920" class="indexterm"/><code class="literal">getClass()</code> method of the
object instead:</p><a id="I_7_tt375"/><pre class="programlisting"> <code class="n">Method</code> <code class="o">[]</code> <code class="n">methods</code> <code class="o">=</code> <code class="n">myUnknownObject</code><code class="o">.</code><code class="na">getClass</code><code class="o">().</code><code class="na">getMethods</code><code class="o">();</code></pre><div class="sect2" title="Modifiers and Security"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-7-SECT-3.1"/>Modifiers and Security</h2></div></div></div><p><a id="idx10361" class="indexterm"/> <a id="idx10380" class="indexterm"/> <a id="idx10385" class="indexterm"/>All of the types of members of a Java class—fields,
methods, constructors, and inner classes—have a method <a id="I_indexterm7_id703991" class="indexterm"/><code class="literal">getModifiers()</code> that
returns a set of flags indicating whether the member is private,
protected, default level, or publicly accessible. You can test for these
with the <a id="I_indexterm7_id704003" class="indexterm"/><code class="literal">java.lang.reflect.Modifier</code> class, like
so:</p><a id="I_7_tt376"/><pre class="programlisting"> <code class="n">Method</code> <code class="n">method</code> <code class="o">=</code> <code class="n">Object</code><code class="o">.</code><code class="na">class</code><code class="o">.</code><code class="na">getDeclaredMethod</code><code class="o">(</code> <code class="s">"clone"</code> <code class="o">);</code> <code class="c1">// no arguments</code>
<code class="kt">int</code> <code class="n">perms</code> <code class="o">=</code> <code class="n">method</code><code class="o">.</code><code class="na">getModifiers</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">Modifier</code><code class="o">.</code><code class="na">isPublic</code><code class="o">(</code> <code class="n">perms</code> <code class="o">)</code> <code class="o">);</code> <code class="c1">// false</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">Modifier</code><code class="o">.</code><code class="na">isProtected</code><code class="o">(</code> <code class="n">perms</code> <code class="o">)</code> <code class="o">);</code> <code class="c1">// true</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">Modifier</code><code class="o">.</code><code class="na">isPrivate</code><code class="o">(</code> <code class="n">perms</code> <code class="o">)</code> <code class="o">);</code> <code class="c1">// false</code></pre><p>In this example, the <code class="literal">clone()</code>
method in <code class="literal">Object</code> is protected.</p><p>Access to the Reflection API is governed by a security manager. A
fully trusted application has access to all the previously discussed
functionality; it can gain access to members of classes at the level of
restriction normally granted code within its scope. It is, however,
possible to grant special access to code so that it can use the
Reflection API to gain access to private and protected members of other
classes in a way that the Java language ordinarily disallows.</p><p>The <code class="literal">Field</code>, <code class="literal">Method</code>, and <code class="literal">Constructor</code> classes all extend from a base
class called <a id="I_indexterm7_id704063" class="indexterm"/><code class="literal">AccessibleObject</code>. The
<code class="literal">AccessibleObject</code> class has one
important method called <code class="literal">setAccessible()</code>, which allows you to
deactivate normal security when accessing that particular class member.
That may sound too easy. It is indeed simple, but whether that method
allows you to disable security or not is a function of the Java security
manager and security policy. You can do this in a normal Java
application running without any security policy, but not, for example,
in an applet or other secure environment. For example, to be able to use
the protected <code class="literal">clone()</code> method of the
<code class="literal">Object</code> class, all we have to do
(given no contravening security manager) is:<a id="I_indexterm7_id704101" class="indexterm"/><a id="I_indexterm7_id704108" class="indexterm"/><a id="I_indexterm7_id704115" class="indexterm"/></p><a id="I_7_tt377"/><pre class="programlisting"> <code class="n">Method</code> <code class="n">method</code> <code class="o">=</code> <code class="n">Object</code><code class="o">.</code><code class="na">class</code><code class="o">.</code><code class="na">getDeclaredMethod</code><code class="o">(</code> <code class="s">"clone"</code> <code class="o">);</code>
<code class="n">method</code><code class="o">.</code><code class="na">setAccessible</code><code class="o">(</code> <code class="kc">true</code> <code class="o">);</code></pre></div><div class="sect2" title="Accessing Fields"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-7-SECT-3.2"/>Accessing Fields</h2></div></div></div><p><a id="idx10356" class="indexterm"/> <a id="idx10376" class="indexterm"/> <a id="idx10382" class="indexterm"/>The class <a id="I_indexterm7_id704180" class="indexterm"/><code class="literal">java.lang.reflect.Field</code>
represents static variables and instance variables. <code class="literal">Field</code> has a full set of overloaded accessor
methods for all the base types (for example, <a id="I_indexterm7_id704198" class="indexterm"/><code class="literal">getInt()</code> and <a id="I_indexterm7_id704208" class="indexterm"/><code class="literal">setInt()</code>, <a id="I_indexterm7_id704219" class="indexterm"/><a id="I_indexterm7_id704224" class="indexterm"/><code class="literal">getBoolean()</code> and
<code class="literal">setBoolean()</code>), and <a id="I_indexterm7_id704240" class="indexterm"/><code class="literal">get()</code> and <a id="I_indexterm7_id704250" class="indexterm"/><code class="literal">set()</code> methods for
accessing fields that are reference types. Let’s consider this
class:</p><a id="I_7_tt378"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">BankAccount</code> <code class="o">{</code>
<code class="kd">public</code> <code class="kt">int</code> <code class="n">balance</code><code class="o">;</code>
<code class="o">}</code></pre><p>With the Reflection API, we can read and modify the value of the
public integer field <code class="literal">balance</code>:</p><a id="I_7_tt379"/><pre class="programlisting"> <code class="n">BankAccount</code> <code class="n">myBankAccount</code> <code class="o">=</code> <code class="o">...;</code>
<code class="o">...</code>
<code class="k">try</code> <code class="o">{</code>
<code class="n">Field</code> <code class="n">balanceField</code> <code class="o">=</code> <code class="n">BankAccount</code><code class="o">.</code><code class="na">class</code><code class="o">.</code><code class="na">getField</code><code class="o">(</code><code class="s">"balance"</code><code class="o">);</code>
<code class="c1">// read it</code>
<code class="kt">int</code> <code class="n">mybalance</code> <code class="o">=</code> <code class="n">balanceField</code><code class="o">.</code><code class="na">getInt</code><code class="o">(</code> <code class="n">myBankAccount</code> <code class="o">);</code>
<code class="c1">// change it</code>
<code class="n">balanceField</code><code class="o">.</code><code class="na">setInt</code><code class="o">(</code> <code class="n">myBankAccount</code><code class="o">,</code> <code class="mi">42</code> <code class="o">);</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">NoSuchFieldException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="o">...</code> <code class="c1">// there is no "balance" field in this class</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">IllegalAccessException</code> <code class="n">e2</code><code class="o">)</code> <code class="o">{</code>
<code class="o">...</code> <code class="c1">// we don't have permission to access the field</code>
<code class="o">}</code></pre><p>In this example, we are assuming that we already know the
structure of a <code class="literal">BankAccount</code> object. In
general, we could gather that information from the object itself.</p><p>All the data access methods of <code class="literal">Field</code> take a reference to the particular
object instance that we want to access. In this example, the <code class="literal">getField()</code> method returns a <code class="literal">Field</code> object that represents the <code class="literal">balance</code> of the <code class="literal">BankAccount</code> class; this object doesn’t refer
to any specific <code class="literal">BankAccount</code>.
Therefore, to read or modify any specific <code class="literal">BankAccount</code>, we call <code class="literal">getInt()</code> and <code class="literal">setInt()</code> with a reference to <code class="literal">myBankAccount</code>, which is the particular object
instance that contains the field with which we want to work. For a
static field, we’d use the value <code class="literal">null</code>
here. An exception occurs if we try to access a field that doesn’t
exist, or if we don’t have the proper permission to read or write to the
field. If we make <code class="literal">balance</code> a private
field, we can still look up the <code class="literal">Field</code>
object that describes it, but we won’t be able to read or write its
value.</p><p>Therefore, we aren’t doing anything that we couldn’t have done
with static code at compile time; as long as <code class="literal">balance</code> is a public member of a class that we
can access, we can write code to read and modify its value. What’s
important is that we’re accessing <code class="literal">balance</code> at runtime, and we could just as
easily use this technique to examine the <code class="literal">balance</code> field in a class that was dynamically
loaded or that we just discovered by iterating through the class’s
fields with the <code class="literal">getDeclaredFields()</code>
method.<a id="I_indexterm7_id704414" class="indexterm"/><a id="I_indexterm7_id704421" class="indexterm"/><a id="I_indexterm7_id704428" class="indexterm"/></p></div><div class="sect2" title="Accessing Methods"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-7-SECT-3.3"/>Accessing Methods</h2></div></div></div><p><a id="idx10357" class="indexterm"/> <a id="idx10377" class="indexterm"/> <a id="idx10383" class="indexterm"/>The class <a id="I_indexterm7_id704484" class="indexterm"/><code class="literal">java.lang.reflect.Method</code> represents a static
or instance method. Subject to the normal security rules, a <code class="literal">Method</code> object’s <a id="I_indexterm7_id704501" class="indexterm"/><code class="literal">invoke()</code> method can be
used to call the underlying object’s method with specified arguments.
Yes, Java does have something like a method pointer!</p><p>As an example, we’ll write a Java application called <code class="literal">Invoke</code> that takes as command-line arguments
the name of a Java class and the name of a method to invoke. For
simplicity, we’ll assume that the method is static and takes no
arguments (quite a limitation):</p><a id="I_7_tt380"/><pre class="programlisting"> <code class="c1">//file: Invoke.java</code>
<code class="kn">import</code> <code class="nn">java.lang.reflect.*</code><code class="o">;</code>
<code class="kd">class</code> <code class="nc">Invoke</code> <code class="o">{</code>
<code class="kd">public</code> <code class="kd">static</code> <code class="kt">void</code> <code class="nf">main</code><code class="o">(</code> <code class="n">String</code> <code class="o">[]</code> <code class="n">args</code> <code class="o">)</code> <code class="o">{</code>
<code class="k">try</code> <code class="o">{</code>
<code class="n">Class</code> <code class="n">clas</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">args</code><code class="o">[</code><code class="mi">0</code><code class="o">]</code> <code class="o">);</code>
<code class="n">Method</code> <code class="n">method</code> <code class="o">=</code> <code class="n">clas</code><code class="o">.</code><code class="na">getMethod</code><code class="o">(</code> <code class="n">args</code><code class="o">[</code><code class="mi">1</code><code class="o">]</code> <code class="o">);</code> <code class="c1">// Named method, </code>
<code class="c1">// no arguments</code>
<code class="n">Object</code> <code class="n">ret</code> <code class="o">=</code> <code class="n">method</code><code class="o">.</code><code class="na">invoke</code><code class="o">(</code> <code class="kc">null</code> <code class="o">);</code> <code class="c1">// Invoke a static method</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="s">"Invoked static method: "</code> <code class="o">+</code> <code class="n">args</code><code class="o">[</code><code class="mi">1</code><code class="o">]</code>
<code class="o">+</code> <code class="s">" of class: "</code> <code class="o">+</code> <code class="n">args</code><code class="o">[</code><code class="mi">0</code><code class="o">]</code>
<code class="o">+</code> <code class="s">" with no args\nResults: "</code> <code class="o">+</code> <code class="n">ret</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="c1">// Class.forName() can't find the class</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">NoSuchMethodException</code> <code class="n">e2</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// that method doesn't exist</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">IllegalAccessException</code> <code class="n">e3</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// we don't have permission to invoke that method</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">InvocationTargetException</code> <code class="n">e4</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// an exception occurred while invoking that method</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="s">"Method threw an: "</code> <code class="o">+</code> <code class="n">e4</code><code class="o">.</code><code class="na">getTargetException</code><code class="o">()</code> <code class="o">);</code>
<code class="o">}</code>
<code class="o">}</code>
<code class="o">}</code></pre><p>We can run <code class="literal">invoke</code> to fetch the
value of the system clock:</p><a id="I_7_tt381"/><pre class="programlisting"> <code class="o">%</code> <strong class="userinput"><code><code class="n">java</code> <code class="n">Invoke</code> <code class="n">java</code><code class="o">.</code><code class="na">lang</code><code class="o">.</code><code class="na">System</code> <code class="n">currentTimeMillis</code></code></strong>
<code class="n">Invoked</code> <code class="kd">static</code> <code class="nl">method:</code> <code class="n">currentTimeMillis</code> <code class="n">of</code> <code class="nl">class:</code>
<code class="n">java</code><code class="o">.</code><code class="na">lang</code><code class="o">.</code><code class="na">System</code> <code class="n">with</code> <code class="n">no</code> <code class="n">args</code>
<code class="nl">Results:</code> <code class="mi">861129235818</code></pre><p>Our first task is to look up the specified <code class="literal">Class</code> by name. To do so, we call the <code class="literal">forName()</code> method with the name of the desired
class (the first command-line argument). We then ask for the specified
method by its name. <code class="literal">getMethod()</code> has
two arguments: the first is the method name (the second command-line
argument), and the second is an array of <code class="literal">Class</code> objects that specifies the method’s
signature. (Remember that any method may be overloaded; you must specify
the signature to make it clear which version you want.) Because our
simple program calls only methods with no arguments, we create an
anonymous empty array of <code class="literal">Class</code>
objects. Had we wanted to invoke a method that takes arguments, we would
have passed an array of the classes of their respective types, in the
proper order. For primitive types, we would have used the standard
wrappers (<code class="literal">Integer</code>, <code class="literal">Float</code>, <code class="literal">Boolean</code>, etc.) to hold the values. The classes
of primitive types in Java are represented by special static <a id="I_indexterm7_id704622" class="indexterm"/><code class="literal">TYPE</code> fields of their
respective wrappers; for example, use <code class="literal">Integer.TYPE</code> for the <code class="literal">Class</code> of an <code class="literal">int</code>. As shown in comments in the code,
starting in Java 5.0, the <code class="literal">getMethod()</code>
and <code class="literal">invoke()</code> methods accept
variable-length argument lists, which means that we can omit the
arguments entirely and Java will make the empty array for us.</p><p>Once we have the <code class="literal">Method</code> object,
we call its <a id="I_indexterm7_id704669" class="indexterm"/><code class="literal">invoke()</code> method. This
calls our target method and returns the result as an <code class="literal">Object</code>. To do anything nontrivial with this
object, you must cast it to something more specific. Presumably, because
we’re calling the method, we know what kind of object to expect. But if
we didn’t, we could use the <code class="literal">Method
getReturnType()</code> method to get the <code class="literal">Class</code> of the return type at runtime. If the
returned value is a primitive type such as <code class="literal">int</code> or <code class="literal">boolean</code>, it will be wrapped in the standard
wrapper class for its type. If the method returns <code class="literal">void</code>, <code class="literal">invoke()</code> returns a <code class="literal">java.lang.Void</code> object. This is the “wrapper”
class that represents <code class="literal">void</code> return
values.</p><p>The first argument to <code class="literal">invoke()</code>
is the object on which we would like to invoke the method. If the method
is static, there is no object, so we set the first argument to <code class="literal">null</code>. That’s the case in our example. The
second argument is an array of objects to be passed as arguments to the
method. The types of these should match the types specified in the call
to <code class="literal">getMethod()</code>. Because we’re calling
a method with no arguments, we can pass <code class="literal">null</code> for the second argument to <code class="literal">invoke()</code>. As with the return value, you must
use wrapper classes for primitive argument types.</p><p>The exceptions shown in the previous code occur if we can’t find
or don’t have permission to access the method. Additionally, an <code class="literal">InvocationTargetException</code> occurs if the method
being invoked throws some kind of exception itself. You can find what it
threw by calling the <code class="literal">getTargetException()</code> method of <code class="literal">InvocationTargetException</code>.<a id="I_indexterm7_id704794" class="indexterm"/><a id="I_indexterm7_id704801" class="indexterm"/><a id="I_indexterm7_id704808" class="indexterm"/></p></div><div class="sect2" title="Accessing Constructors"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-7-SECT-3.4"/>Accessing Constructors</h2></div></div></div><p><a id="I_indexterm7_id704822" class="indexterm"/> <a id="idx10375" class="indexterm"/> <a id="I_indexterm7_id704848" class="indexterm"/>The <a id="I_indexterm7_id704856" class="indexterm"/><code class="literal">java.lang.reflect.Constructor</code> class represents
an object constructor in the same way that the <code class="literal">Method</code> class represents a method. You can use
it, subject to the security manager, of course, to create a new instance
of an object, even with constructors that require arguments. Recall that
you can create instances of a class with <code class="literal">Class.newInstance()</code>, but you cannot specify
arguments with that method. This is the solution to that problem, if you
really need to do it.</p><p>Here, we’ll create an instance of <code class="literal">java.util.Date</code>,<sup>[<a id="learnjava3-CHP-7-FNOTE-1" href="#ftn.learnjava3-CHP-7-FNOTE-1" class="footnote">20</a>]</sup> passing a string argument to the constructor:</p><a id="I_7_tt382"/><pre class="programlisting"><code class="k">try</code> <code class="o">{</code>
<code class="n">Constructor</code><code class="o"><</code><code class="n">Date</code><code class="o">></code> <code class="n">cons</code> <code class="o">=</code>
<code class="n">Date</code><code class="o">.</code><code class="na">class</code><code class="o">.</code><code class="na">getConstructor</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="n">Date</code> <code class="n">date</code> <code class="o">=</code> <code class="n">cons</code><code class="o">.</code><code class="na">newInstance</code><code class="o">(</code> <code class="s">"Jan 1, 2006"</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">date</code> <code class="o">);</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">NoSuchMethodException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// getConstructor() couldn't find the constructor we described</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">InstantiationException</code> <code class="n">e2</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// the class is abstract</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">IllegalAccessException</code> <code class="n">e3</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// we don't have permission to create an instance</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">InvocationTargetException</code> <code class="n">e4</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// the construct threw an exception</code>
<code class="o">}</code></pre><p>The story is much the same as with a method invocation; after all,
a constructor is really no more than a method with some strange
properties. We look up the appropriate constructor for our <code class="literal">Date</code> class—the one that takes a single
<code class="literal">String</code> as its argument—by passing
<code class="literal">getConstructor()</code> the <code class="literal">String.class</code> type. Here, we are using the Java
5.0 variable argument syntax. If the constructor required more
arguments, we would pass additional <code class="literal">Class</code>es representing the class of each
argument. We can then invoke <code class="literal">newInstance()</code>, passing it a corresponding
argument object. Again, to pass primitive types, we would wrap them in
their wrapper types first. Finally, we print the resulting object to a
<code class="literal">Date</code>. Note that we’ve slipped in
another strange construct using generics here. The <code class="literal">Constructor<Date></code> type here simply
allows us to specialize the <code class="literal">Constructor</code> for the <code class="literal">Date</code> type, alleviating the need to cast the
result of the <code class="literal">newInstance()</code> method,
as before.</p><p>The exceptions from the previous example apply here, too, along
with <a id="I_indexterm7_id704995" class="indexterm"/><code class="literal">IllegalArgumentException</code> and <a id="I_indexterm7_id705006" class="indexterm"/><code class="literal">InstantiationException</code>.
The latter is thrown if the class is <code class="literal">abstract</code>
and, therefore, can’t be instantiated.<a id="I_indexterm7_id705028" class="indexterm"/></p></div><div class="sect2" title="What About Arrays?"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-7-SECT-3.5"/>What About Arrays?</h2></div></div></div><p><a id="idx10358" class="indexterm"/> <a id="idx10378" class="indexterm"/> <a id="I_indexterm7_id705071" class="indexterm"/>The Reflection API allows you to create and inspect arrays
of base types using the <a id="I_indexterm7_id705080" class="indexterm"/><code class="literal">java.lang.reflect.Array</code>
class. The process is very much the same as with the other classes, so
we won’t cover it in detail. The primary feature is a static method of
<code class="literal">Array</code> called <a id="I_indexterm7_id705099" class="indexterm"/><code class="literal">newInstance()</code>, which
creates an array that allows you to specify a base type and length. You
can also use it to construct multidimensional array instances by
specifying an array of lengths (one for each dimension). For more
information, look in your favorite Java language reference.<a id="I_indexterm7_id705112" class="indexterm"/><a id="I_indexterm7_id705119" class="indexterm"/></p></div><div class="sect2" title="Accessing Generic Type Information"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-7-SECT-3.6"/>Accessing Generic Type Information</h2></div></div></div><p><a id="I_indexterm7_id705133" class="indexterm"/> <a id="I_indexterm7_id705144" class="indexterm"/> <a id="I_indexterm7_id705155" class="indexterm"/>In <a class="xref" href="ch08.html" title="Chapter 8. Generics">Chapter 8</a>, we’ll discuss
generics, which first appeared in Java 5.0. Generics is a major addition
that adds new dimensions (literally) to the concept of types in the Java
language. With the addition of generics, types are no longer simply
one-to-one with Java classes and interfaces but can be parameterized on
one or more types to create a new, generic type. To make matters more
complicated, these new types do not actually generate new classes, but
instead are artifacts of the compiler. To keep the generic information,
Java adds information to the compiled class files.</p><p>The Reflection API can accommodate all of this, mainly through the
addition of the new <a id="I_indexterm7_id705182" class="indexterm"/><code class="literal">java.lang.reflect.Type</code>
class, which is capable of representing generic types. Covering this in
detail is a bit outside the scope of this book and because we won’t even
get to generics until <a class="xref" href="ch08.html" title="Chapter 8. Generics">Chapter 8</a>, we won’t
devote much more space to this topic here. However, the following code
snippets may guide you later if you return to the topic of accessing
generic type information reflectively:</p><a id="I_7_tt383"/><pre class="programlisting"> <code class="c1">// public interface List<E> extends Collection<E> { ... }</code>
<code class="n">TypeVariable</code> <code class="o">[]</code> <code class="n">tv</code> <code class="o">=</code> <code class="n">List</code><code class="o">.</code><code class="na">class</code><code class="o">.</code><code class="na">getTypeParameters</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">tv</code><code class="o">[</code><code class="mi">0</code><code class="o">].</code><code class="na">getName</code><code class="o">()</code> <code class="o">);</code> <code class="c1">// "E"</code></pre><p>This snippet gets the type parameter of the <code class="literal">java.util.List</code> class and prints its
name:</p><a id="I_7_tt384"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">StringList</code> <code class="kd">extends</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="o">}</code>
<code class="n">Type</code> <code class="n">type</code> <code class="o">=</code> <code class="n">StringList</code><code class="o">.</code><code class="na">class</code><code class="o">.</code><code class="na">getGenericSuperclass</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">type</code> <code class="o">);</code> <code class="c1">//</code>
<code class="c1">// "java.util.ArrayList<java.lang.String>"</code>
<code class="n">ParameterizedType</code> <code class="n">pt</code> <code class="o">=</code> <code class="o">(</code><code class="n">ParameterizedType</code><code class="o">)</code><code class="n">type</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">pt</code><code class="o">.</code><code class="na">getActualTypeArguments</code><code class="o">()[</code><code class="mi">0</code><code class="o">]</code> <code class="o">);</code> <code class="c1">//</code>
<code class="c1">// "class java.lang.String"</code></pre><p>This second snippet gets the <code class="literal">Type</code> for a class that extends a generic type
and then prints the actual type on which it was parameterized.</p></div><div class="sect2" title="Accessing Annotation Data"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-7-SECT-3.7"/>Accessing Annotation Data</h2></div></div></div><p><a id="I_indexterm7_id705251" class="indexterm"/> <a id="I_indexterm7_id705262" class="indexterm"/> <a id="I_indexterm7_id705273" class="indexterm"/>Later in this chapter, we discuss annotations, a feature
that allows metadata to be added to Java classes, methods, and fields.
Annotations can optionally be retained in the compiled Java classes and
accessed through the Reflection API. This is one of several intended
uses for annotations, allowing code at runtime to see the metadata and
provide special services for the annotated code. For example, a property
(field or setter method) on a Java object might be annotated to indicate
that it is expecting a container application to set its value or export
it in some way.</p><p>Covering this in detail is outside the scope of this book;
however, getting annotation data through the Reflection API is easy.
Java classes, as well as <code class="literal">Method</code> and
<code class="literal">Field</code> objects, have the following
pairs of methods (and some other related ones):</p><a id="I_7_tt385"/><pre class="programlisting"> <code class="kd">public</code> <code class="o"><</code><code class="n">A</code> <code class="kd">extends</code> <code class="n">Annotation</code><code class="o">></code> <code class="n">A</code> <code class="n">getAnnotation</code><code class="o">(</code><code class="n">Class</code><code class="o"><</code><code class="n">A</code><code class="o">></code> <code class="n">annotationClass</code><code class="o">)</code>
<code class="kd">public</code> <code class="n">Annotation</code><code class="o">[]</code> <code class="nf">getDeclaredAnnotations</code><code class="o">()</code></pre><p>These methods (the first is a generic method, as covered in <a class="xref" href="ch08.html" title="Chapter 8. Generics">Chapter 8</a>) return <code class="literal">java.lang.annotation.Annotation</code> type objects
that represent the metadata.</p></div><div class="sect2" title="Dynamic Interface Adapters"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-7-SECT-3.8"/>Dynamic Interface Adapters</h2></div></div></div><p><a id="idx10360" class="indexterm"/> <a id="idx10379" class="indexterm"/> <a id="idx10384" class="indexterm"/>Ideally, Java reflection would allow us to do everything
at runtime that we can do at compile time (without forcing us to
generate and compile source into bytecode). But that is not entirely the
case. Although we can dynamically load and create instances of objects
at runtime using the <code class="literal">Class.forName()</code>
method, there is no general way to create new types of objects—for which
no class files preexist—on the fly.</p><p>The <a id="I_indexterm7_id705388" class="indexterm"/><code class="literal">java.lang.reflect.Proxy</code>
class, however, takes a step toward solving this problem by allowing the
creation of adapter objects that implement arbitrary Java interfaces at
runtime. The <code class="literal">Proxy</code> class is a factory
that can generate an adapter class, implementing any interface (or
interfaces) you want. When methods are invoked on the adapter class,
they are delegated to a single method in a designated <code class="literal">InvocationHandler</code> object. You can use this to
create dynamic implementations of any kind of interface at runtime and
handle the method calls anywhere you want. For example, using a <code class="literal">Proxy</code>, you could log all of the method calls
on an interface, delegating them to a “real” implementation afterward.
This kind of dynamic behavior is important for tools that work with Java
beans, which must register event listeners. (We’ll mention this again in
<a class="xref" href="ch22.html" title="Chapter 22. JavaBeans">Chapter 22</a>.) It’s also useful for a wide range
of problems.</p><p>In the following snippet, we take an interface name and construct
a proxy implementing the interface. It outputs a message whenever any of
the interface’s methods are invoked:</p><a id="I_7_tt386"/><pre class="programlisting"> <code class="kn">import</code> <code class="nn">java.lang.reflect.*</code><code class="o">;</code>
<code class="n">InvocationHandler</code> <code class="n">handler</code> <code class="o">=</code>
<code class="k">new</code> <code class="nf">InvocationHandler</code><code class="o">()</code> <code class="o">{</code>
<code class="n">Object</code> <code class="nf">invoke</code><code class="o">(</code> <code class="n">Object</code> <code class="n">proxy</code><code class="o">,</code> <code class="n">Method</code> <code class="n">method</code><code class="o">,</code> <code class="n">Object</code><code class="o">[]</code> <code class="n">args</code> <code class="o">)</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="s">"Method: {[QUOTE-REPLACEMENT]}+ method.getName() +"</code><code class="o">()</code><code class="s">"</code>
<code class="s"> +"</code> <code class="n">of</code> <code class="nl">interface:</code> <code class="s">"+ interfaceName</code>
<code class="s"> + "</code> <code class="n">invoked</code> <code class="n">on</code> <code class="n">proxy</code><code class="o">!</code><code class="err">"</code>
<code class="o">);</code>
<code class="k">return</code> <code class="kc">null</code><code class="o">;</code>
<code class="o">}</code>
<code class="o">};</code>
<code class="n">Class</code> <code class="n">clas</code> <code class="o">=</c