📄 chap12.htm
字号:
Class c = <font color=#0000ff>null</font>;
<font color=#0000ff>try</font> {
c = Class.forName(<font color=#004488>"FancyToy"</font>);
} <font color=#0000ff>catch</font>(ClassNotFoundException e) {
System.err.println(<font color=#004488>"Can't find FancyToy"</font>);
<font color=#0000ff>throw</font> e;
}
printInfo(c);
Class[] faces = c.getInterfaces();
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < faces.length; i++)
printInfo(faces[i]);
Class cy = c.getSuperclass();
Object o = <font color=#0000ff>null</font>;
<font color=#0000ff>try</font> {
<font color=#009900>// Requires default constructor:</font>
o = cy.newInstance(); <font color=#009900>// (*1*)</font>
} <font color=#0000ff>catch</font>(InstantiationException e) {
System.err.println(<font color=#004488>"Cannot instantiate"</font>);
<font color=#0000ff>throw</font> e;
} <font color=#0000ff>catch</font>(IllegalAccessException e) {
System.err.println(<font color=#004488>"Cannot access"</font>);
<font color=#0000ff>throw</font> e;
}
printInfo(o.getClass());
}
<font color=#0000ff>static</font> <font color=#0000ff>void</font> printInfo(Class cc) {
System.out.println(
<font color=#004488>"Class name: "</font> + cc.getName() +
<font color=#004488>" is interface? ["</font> +
cc.isInterface() + <font color=#004488>"]"</font>);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can see that <B>class FancyToy</B> is
quite complicated, since it inherits from <B>Toy</B> and <B>implements</B> the
<B>interface</B>s of <B>HasBatteries</B>, <B>Waterproof</B>, and
<B>ShootsThings</B>. In <B>main( )</B>, a <B>Class</B> reference is created
and initialized to the <B>FancyToy</B> <B>Class</B> using <B>forName( )</B>
inside an appropriate <B>try</B> block.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I30'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER12_I31>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>Class.getInterfaces( )</B>
<A NAME="Index1509"></A><A NAME="Index1510"></A>method returns an array of
<B>Class</B> objects representing the interfaces that are contained in the
<B>Class</B> object of interest.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I31'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER12_I32>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you have a <B>Class</B> object you can
also ask it for its direct base class using
<A NAME="Index1511"></A><A NAME="Index1512"></A><B>getSuperclass( )</B>.
This, of course, returns a <B>Class</B> reference that you can further query.
This means that, at run-time, you can discover an object’s entire class
hierarchy.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I32'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER12_I33>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The
<A NAME="Index1513"></A><A NAME="Index1514"></A><B>newInstance( )</B>
method of <B>Class</B> can, at first, seem like just another way to
<B>clone( )</B> an object. However, you can create a new object with
<B>newInstance( )</B> <I>without</I> an existing object, as seen here,
because there is no <B>Toy</B> object—only <B>cy</B>, which is a reference
to <B>y</B>’s <B>Class</B> object. This is a way to implement a
“virtual constructor,” which allows you to say “I don’t
know exactly what type you are, but create yourself properly anyway.” In
the example above, <B>cy</B> is just a <B>Class</B> reference with no further
type information known at compile-time. And when you create a new instance, you
get back an <B>Object reference</B>. But that reference is pointing to a
<B>Toy</B> object. Of course, before you can send any messages other than those
accepted by <B>Object</B>, you have to investigate it a bit and do some casting.
In addition, the class that’s being created with
<B>newInstance( )</B> must have a default constructor. In the next section,
you’ll see how<B> </B>to dynamically create objects of classes using any
constructor, with the Java <I>reflection</I> API.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I33'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER12_I34>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The final method in the listing is
<A NAME="Index1515"></A><A NAME="Index1516"></A><B>printInfo( ),</B> which
takes a <B>Class</B> reference and gets its name with
<A NAME="Index1517"></A><A NAME="Index1518"></A><B>getName( ),</B> and
finds out whether it’s an interface with
<A NAME="Index1519"></A><A NAME="Index1520"></A><B>isInterface( )</B>.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I34'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER12_I35>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The output from this program
is:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>Class name: FancyToy is <font color=#0000ff>interface</font>? [<font color=#0000ff>false</font>]
Class name: HasBatteries is <font color=#0000ff>interface</font>? [<font color=#0000ff>true</font>]
Class name: Waterproof is <font color=#0000ff>interface</font>? [<font color=#0000ff>true</font>]
Class name: ShootsThings is <font color=#0000ff>interface</font>? [<font color=#0000ff>true</font>]
Class name: Toy is <font color=#0000ff>interface</font>? [<font color=#0000ff>false</font>]</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Thus, with the <B>Class</B> object you
can find out just about everything you want to know about an object.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I35'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER12_I36>
</FONT><A NAME="_Toc312374147"></A><A NAME="_Toc375545410"></A><A NAME="_Toc481064777"></A><BR></P></DIV>
<A NAME="Heading410"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Reflection: run-time <BR>class
information<BR><A NAME="Index1521"></A><A NAME="Index1522"></A></H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you don’t know the precise type
of an object, RTTI will tell you. However, there’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’re working with for RTTI.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I36'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER12_I37>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This doesn’t seem like that much of
a limitation at first, but suppose you’re given a reference to an object
that’s not in your program space. In fact, the class of the object
isn’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’re told that those bytes represent a class. Since the compiler
can’t know about the class while it’s compiling the code, how can
you possibly use such a class?
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I37'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER12_I38>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">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="Index1523"></A><I>Rapid Application Development</I> (RAD) in an
application builder tool. This is a visual approach to creating a program (which
you see on the screen as a “form”) 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, that it exposes parts of itself, and that it
allows 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 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="Index1524"></A>Java provides a structure for
component-based programming through JavaBeans (described in Chapter 13).
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I38'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER12_I39>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">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
<I>Remote Method Invocation</I> (RMI) and it allows a Java program to have
objects distributed across many machines. This distribution can happen for a
number of reasons: for example, perhaps you’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., “Business
Rules” in a multitier 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—matrix inversions, for
example—but inappropriate or too expensive for general purpose
programming.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I39'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER12_I40>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The class <B>Class</B> (described
previously in this chapter) supports the concept of <I>reflection</I>, and
there’s an additional library, <B>java.lang.reflect, </B>with classes
<A NAME="Index1525"></A><A NAME="Index1526"></A><B>Field</B>,
<A NAME="Index1527"></A><A NAME="Index1528"></A><B>Method</B>, and
<A NAME="Index1529"></A><A NAME="Index1530"></A><B>Constructor </B>(each of
which implement the <B>Member interface</B>). 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 <B>Constructor</B>s to create new objects, the
<B>get( )</B> and <B>set( )</B> methods to read and modify the fields
associated with <B>Field</B> objects, and the <B>invoke( )</B> method to
call a method associated with a <B>Method</B> object. In addition, you can call
the convenience methods <B>getFields( )</B>, <B>getMethods( )</B>,
<B>getConstructors( )</B>, etc., to return arrays of the objects
representing the fields, methods, and constructors. (You can find out more by
looking up the class <B>Class</B> in your online documentation.)<B> </B>Thus,
the class information for anonymous objects can be completely determined at
run-time, and nothing need be known at compile-time.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I40'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER12_I41>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It’s important to realize that
there’s nothing magic about reflection. When you’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 <B>Class</B> object must be
loaded. Thus, the <B>.class</B> 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="Index1531"></A><A NAME="Index1532"></A>difference between RTTI and
reflection is that with RTTI, the compiler opens and examines the <B>.class</B>
file at compile-time. Put another way, you can call all the methods of an object
in the “normal” way. With reflection, the <B>.class</B> file is
unavailable at compile-time; it is opened and examined by the run-time
environment.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I41'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER12_I42>
</FONT><A NAME="_Toc481064778"></A><BR></P></DIV>
<A NAME="Heading411"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
A class method extractor</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You’ll rarely need to use the
reflection tools directly; they’re in the language to support other Java
f
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -