📄 tij0122.html
字号:
}
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods <A NAME="Index1428"></A><A NAME="Index1429"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>getMethods( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and <A NAME="Index1430"></A><A NAME="Index1431"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>getConstructors( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
return an array of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Method</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Constructor</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
respectively. Each of these classes has further methods to dissect the names,
arguments, and return values of the methods they represent. But you can also
just use
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>toString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
as is done here, to produce a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
with the entire method signature. The rest of the code is just for extracting
command line information, determining if a particular signature matches with
your target string (using <A NAME="Index1432"></A><A NAME="Index1433"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>indexOf( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">),
and printing the results.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
shows reflection in action, since the result produced by
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Class.forName( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
cannot be known at compile-time, and therefore all the method signature
information is being extracted at run-time. If you investigate your online
documentation on reflection, you’ll see that there is enough support to
actually set up and make a method call on an object that’s totally
unknown at compile-time. Again, this is something you’ll probably never
need to do yourself – the support is there for Java and so a programming
environment can manipulate Java Beans – but it’s interesting.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">An
interesting experiment is to run
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>java
ShowMethods ShowMethods
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
This produces a listing that includes a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
default constructor, even though you can see from the code that no constructor
was defined. The constructor you see is the one that’s automatically
synthesized by the compiler. If you then make
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ShowMethods</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
a non-
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class (that is, friendly), the synthesized default constructor no longer shows
up in the output. The synthesized default constructor is automatically given
the same access as the class.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
output for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ShowMethods</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is still a little tedious. For example, here’s a portion of the output
produced by invoking
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>java
ShowMethods java.lang.String
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">:</FONT><P></DIV>
<font color="#990000"><PRE><font color="#0000ff">public</font> <font color="#0000ff">boolean</font>
java.lang.String.startsWith(java.lang.String,<font color="#0000ff">int</font>)
<font color="#0000ff">public</font> <font color="#0000ff">boolean</font>
java.lang.String.startsWith(java.lang.String)
<font color="#0000ff">public</font> <font color="#0000ff">boolean</font> </TT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black"> java.lang.String.endsWith(java.lang.String) </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">It
would be even nicer if the qualifiers like
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>java.lang</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
could be stripped off. The <A NAME="Index1434"></A><A NAME="Index1435"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>StreamTokenizer</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class introduced in the previous chapter can help solve this problem:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: ShowMethodsClean.java</font>
<font color="#009900">// ShowMethods with the qualifiers stripped</font>
<font color="#009900">// to make the results easier to read</font>
<font color="#0000ff">import</font> java.lang.reflect.*;
<font color="#0000ff">import</font> java.io.*;
<font color="#0000ff">public</font> <font color="#0000ff">class</font> ShowMethodsClean {
<font color="#0000ff">static</font> <font color="#0000ff">final</font> String usage =
"usage: \n" +
"ShowMethodsClean qualified.<font color="#0000ff">class</font>.name\n" +
"To show all methods in <font color="#0000ff">class</font> or: \n" +
"ShowMethodsClean qualif.<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 < 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="#009900">// Convert to an array of cleaned Strings:</font>
String[] n =
<font color="#0000ff">new</font> String[m.length + ctor.length];
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i < m.length; i++) {
String s = m[i].toString();
n[i] = StripQualifiers.strip(s);
}
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i < ctor.length; i++) {
String s = ctor[i].toString();
n[i + m.length] =
StripQualifiers.strip(s);
}
<font color="#0000ff">if</font>(args.length == 1)
<font color="#0000ff">for</font> (<font color="#0000ff">int</font> i = 0; i < n.length; i++)
System.out.println(n[i]);
<font color="#0000ff">else</font>
<font color="#0000ff">for</font> (<font color="#0000ff">int</font> i = 0; i < n.length; i++)
<font color="#0000ff">if</font>(n[i].indexOf(args[1])!= -1)
System.out.println(n[i]);
} <font color="#0000ff">catch</font> (ClassNotFoundException e) {
System.out.println("No such <font color="#0000ff">class</font>: " + e);
}
}
}
<font color="#0000ff">class</font> StripQualifiers {
<font color="#0000ff">private</font> StreamTokenizer st;
<font color="#0000ff">public</font> StripQualifiers(String qualified) {
st = <font color="#0000ff">new</font> StreamTokenizer(
<font color="#0000ff">new</font> StringReader(qualified));
st.ordinaryChar(' '); <font color="#009900">// Keep the spaces</font>
}
<font color="#0000ff">public</font> String getNext() {
String s = <font color="#0000ff">null</font>;
<font color="#0000ff">try</font> {
<font color="#0000ff">if</font>(st.nextToken() !=
StreamTokenizer.TT_EOF) {
<font color="#0000ff">switch</font>(st.ttype) {
<font color="#0000ff">case</font> StreamTokenizer.TT_EOL:
s = <font color="#0000ff">null</font>;
<font color="#0000ff">break</font>;
<font color="#0000ff">case</font> StreamTokenizer.TT_NUMBER:
s = Double.toString(st.nval);
<font color="#0000ff">break</font>;
<font color="#0000ff">case</font> StreamTokenizer.TT_WORD:
s = <font color="#0000ff">new</font> String(st.sval);
<font color="#0000ff">break</font>;
<font color="#0000ff">default</font>: <font color="#009900">// single character in ttype</font>
s = String.valueOf((<font color="#0000ff">char</font>)st.ttype);
}
}
} <font color="#0000ff">catch</font>(IOException e) {
System.out.println(e);
}
<font color="#0000ff">return</font> s;
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> String strip(String qualified) {
StripQualifiers sq =
<font color="#0000ff">new</font> StripQualifiers(qualified);
String s = "", si;
<font color="#0000ff">while</font>((si = sq.getNext()) != <font color="#0000ff">null</font>) {
<font color="#0000ff">int</font> lastDot = si.lastIndexOf('.');
<font color="#0000ff">if</font>(lastDot != -1)
si = si.substring(lastDot + 1);
s += si;
}
<font color="#0000ff">return</font> s;
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ShowMethodsClean</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is quite similar to the previous
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ShowMethods</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
except that it takes the arrays of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Method</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Constructor</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and converts them into a single array of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Each of these
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects is then passed through
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
StripQualifiers.Strip( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to remove all the method qualification. As you can see, this uses the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>StreamTokenizer</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
manipulation to do its work.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
tool can be a real time-saver while you’re programming, when you
can’t remember if a class has a particular method and you don’t
want to go walking through the class hierarchy in the online documentation, or
if you don’t know whether that class can do anything with, for example,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Color</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Chapter
17 contains a GUI version of this program so you can leave it running while
you’re writing code, to allow quick lookups.
</FONT><a name="_Toc408018651"></a><a name="_Toc375545411"></a><P></DIV>
<div align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0121.html">Prev</a> | <a href="tij0123.html">Next</a>
</div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -