⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tij0122.html

📁 学习java的经典书籍
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<html><body>

<table width="100%"><tr>
<td>
<a href="http://www.bruceeckel.com/javabook.html">Bruce Eckel's Thinking in Java</a>
</td>
<td align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0121.html">Prev</a> | <a href="tij0123.html">Next</a>
</td>
</tr></table>
<hr>

<H2 ALIGN=LEFT>
Reflection:
run-time 
<P>class
information
<P><A NAME="Index1415"></A><A NAME="Index1416"></A></H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you don&#8217;t know the precise type of an object, RTTI will tell you.
However, there&#8217;s a limitation: the type must be known at compile time in
order for you to be able to detect it using RTTI and do something useful with
the information. Put another way, the compiler must know about all the classes
you&#8217;re working with for RTTI.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
doesn&#8217;t seem like that much of a limitation at first, but suppose
you&#8217;re given a handle to an object that&#8217;s not in your program
space. In fact, the class of the object isn&#8217;t even available to your
program at compile time. For example, suppose you get a bunch of bytes from a
disk file or from a network connection and you&#8217;re told that those bytes
represent a class. Since the compiler can&#8217;t know about the class while
it&#8217;s compiling the code, how can you possibly use such a class?
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
a traditional programming environment this seems like a far-fetched scenario.
But as we move into a larger programming world there are important cases in
which this happens. The first is component-based programming in which you build
projects using <A NAME="Index1417"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>Rapid
Application Development
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(RAD) in an application builder tool. This is a visual approach to creating a
program (which you see on the screen as a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>form</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)
by moving icons that represent components onto the form. These components are
then configured by setting some of their values at program time. This
design-time configuration requires that any component be instantiable and that
it expose some part of itself and allow its values to be read and set. In
addition, components that handle GUI events must expose information about
appropriate methods so that the RAD environment 
<a name="may"></a>can
assist the programmer in overriding these event-handling methods. Reflection
provides the mechanism to detect the available methods and produce the method
names. <A NAME="Index1418"></A>Java
1.1 provides a structure for component-based programming through Java Beans
(described in Chapter 13).
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Another
compelling motivation for discovering class information at run-time is to
provide the ability to create and execute objects on remote platforms across a
network. This is called 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>Remote
Method Invocation
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(RMI) and it allows a Java program (version 1.1 and higher) to have objects
distributed across many machines. This distribution can happen for a number of
reasons: perhaps you&#8217;re doing a computation-intensive task and you want
to break it up and put pieces on machines that are idle in order to speed
things up. In some situations you might want to place code that handles
particular types of tasks (e.g. &#8220;Business Rules&#8221; in a multi-tier
client/server architecture) on a particular machine so that machine becomes a
common repository describing those actions and it can be easily changed to
affect everyone in the system. (This is an interesting development since the
machine exists solely to make software changes easy!) Along these lines,
distributed computing also supports specialized hardware that might be good at
a particular task &#8211; matrix inversions, for example &#8211; but
inappropriate or too expensive for general purpose programming.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
Java 1.1<A NAME="Index1419"></A>,
the class 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(described previously in this chapter) is extended to support the concept of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>reflection</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and there&#8217;s an additional library, 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>java.lang.reflect,
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">with
classes <A NAME="Index1420"></A><A NAME="Index1421"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Field</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
<A NAME="Index1422"></A><A NAME="Index1423"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Method</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and <A NAME="Index1424"></A><A NAME="Index1425"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Constructor
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">(each
of which implement the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Member
interface
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">).
Objects of these types are created by the JVM at run-time to represent the
corresponding member in the unknown class. You can then use the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Constructor</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s
to create new objects, the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>get(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>set(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods to read and modify the fields associated with 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Field</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects, and the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>invoke(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method to call a method associated with a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Method</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object. In addition, you can call the convenience methods 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>getFields(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>getMethods(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>getConstructors(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
etc., to return arrays of the objects representing the fields, methods, and
constructors. (You can find out more by looking up the class 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in your online documentation.)
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Thus,
the class information for anonymous objects can be completely determined at run
time, and nothing need be known at compile time.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">It&#8217;s
important to realize that there&#8217;s nothing magic about reflection. When
you&#8217;re using reflection to interact with an object of an unknown type,
the JVM will simply look at the object and see that it belongs to a particular
class (just like ordinary RTTI) but then, before it can do anything else, the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object must be loaded. Thus, the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>.class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
file for that particular type must still be available to the JVM, either on the
local machine or across the network. So the true <A NAME="Index1426"></A><A NAME="Index1427"></A>difference
between RTTI and reflection is that with RTTI, the compiler opens and examines
the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>.class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
file at compile time. Put another way, you can call all the methods of an
object in the &#8220;normal&#8221; way. With reflection, the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>.class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
file is unavailable at compile time; it is opened and examined by the run-time
environment.
</FONT><a name="_Toc408018650"></a><P></DIV>
<A NAME="Heading361"></A><H3 ALIGN=LEFT>
A
class method extractor
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You&#8217;ll
rarely need to use the reflection tools directly; they&#8217;re in the language
to support the other Java features such as object serialization (described in
Chapter 10), Java Beans, and RMI (described later in the book). However, there
are times when it&#8217;s quite useful to be able to dynamically extract
information about a class. One extremely useful tool is a class method
extractor. As mentioned before, looking at a class definition source code or
online documentation shows only the methods that are defined or overridden 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>within
that class definition
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
But there could be dozens more available to you that have come from base
classes. To locate these is both tedious and time consuming. Fortunately,
reflection provides a way to write a simple tool that will automatically show
you the entire interface. Here&#8217;s the way it works:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">//: ShowMethods.java</font>
<font color="#009900">// Using Java 1.1 reflection to show all the </font>
<font color="#009900">// methods of a class, even if the methods are </font>
<font color="#009900">// defined in the base class.</font>
<font color="#0000ff">import</font> java.lang.reflect.*;

<font color="#0000ff">public</font> <font color="#0000ff">class</font> ShowMethods {
  <font color="#0000ff">static</font> <font color="#0000ff">final</font> String usage =
    "usage: \n" +
    "ShowMethods qualified.<font color="#0000ff">class</font>.name\n" +
    "To show all methods in <font color="#0000ff">class</font> or: \n" +
    "ShowMethods qualified.<font color="#0000ff">class</font>.name word\n" +
    "To search <font color="#0000ff">for</font> methods involving 'word'";
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
    <font color="#0000ff">if</font>(args.length &lt; 1) {
      System.out.println(usage);
      System.exit(0);
    }
    <font color="#0000ff">try</font> {
      Class c = Class.forName(args[0]);
      Method[] m = c.getMethods();
      Constructor[] ctor = c.getConstructors();
      <font color="#0000ff">if</font>(args.length == 1) {
        <font color="#0000ff">for</font> (<font color="#0000ff">int</font> i = 0; i &lt; m.length; i++)
          System.out.println(m[i].toString());
        <font color="#0000ff">for</font> (<font color="#0000ff">int</font> i = 0; i &lt; ctor.length; i++)
          System.out.println(ctor[i].toString());
      } 
      <font color="#0000ff">else</font> {
        <font color="#0000ff">for</font> (<font color="#0000ff">int</font> i = 0; i &lt; m.length; i++)
          <font color="#0000ff">if</font>(m[i].toString()
             .indexOf(args[1])!= -1)
            System.out.println(m[i].toString());
        <font color="#0000ff">for</font> (<font color="#0000ff">int</font> i = 0; i &lt; ctor.length; i++)
          <font color="#0000ff">if</font>(ctor[i].toString()
             .indexOf(args[1])!= -1)
          System.out.println(ctor[i].toString());
      }
    } <font color="#0000ff">catch</font> (ClassNotFoundException e) {
      System.out.println("No such <font color="#0000ff">class</font>: " + e);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -