UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

364 lines (355 loc) 57.2 kB
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"><head><title>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">&lt;</code><code class="n">Date</code><code class="o">&gt;</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&lt;Date&gt;</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&lt;E&gt; extends Collection&lt;E&gt; { ... }</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">&lt;</code><code class="n">String</code><code class="o">&gt;</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&lt;java.lang.String&gt;"</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">&lt;</code><code class="n">A</code> <code class="kd">extends</code> <code class="n">Annotation</code><code class="o">&gt;</code> <code class="n">A</code> <code class="n">getAnnotation</code><code class="o">(</code><code class="n">Class</code><code class="o">&lt;</code><code class="n">A</code><code class="o">&gt;</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