📄 tij312.htm
字号:
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p><a name="_Toc305593310"></a><a name="_Toc305628782"></a>In <b>main( )</b> an array <b>petTypes </b>of <b>Class</b> objects is created using <b>Class.forName( )</b>. Since the <b>Pet</b> objects are in package <b>c09</b>, the package name must be used when naming the classes. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0489" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Next, the <b>pets</b> array is filled by randomly indexing into <b>petTypes </b>and using the selected <b>Class</b> object to generate a new instance of that class with <b>Class.newInstance( )</b>, which uses the default (no-arg) class constructor to generate the new object. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0490" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Both <b>forName( )</b> and <b>newInstance( )</b> can generate exceptions, which you can see handled in the <b>catch</b> clauses following the <b>try</b> block. Again, the names of the exceptions are relatively useful explanations of what went wrong (<b>IllegalAccessException</b> relates to a violation of the Java security mechanism). <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0491" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>After creating the <b>AssociativeArray</b>, it is filled with key-value pairs of pet names and <b>Counter</b> objects. Then each <b>Pet</b> in the randomly-generated array is tested and counted using <b>instanceof</b>. The array and <b>AssociativeArray</b> are printed so you can compare the results. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0492" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>There’s a rather narrow restriction on <b>instanceof</b>: You can compare it to a named type only, and not to a <b>Class</b> object. In the preceding example you might feel that it’s tedious to write out all of those <b>instanceof</b> expressions, and you’re right. But there is no way to cleverly automate <b>instanceof </b>by creating an array of <b>Class</b> objects and comparing it to those instead (stay tuned—you’ll see an alternative). This isn’t as great a restriction as you might think, because you’ll eventually understand that your design is probably flawed if you end up writing a lot of <b>instanceof</b> expressions. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap12_1850" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Of course, this example is contrived—you’d probably put a <b>static</b> field in each type and increment it in the constructor to keep track of the counts. You would do something like that <i>if</i> you had control of the source code for the class and could change it. Since this is not always the case, RTTI can come in handy. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap12_1851" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h4>
<a name="Heading9795"></a>Using class literals</h4>
<p>It’s interesting to see how the <b>PetCount.java</b> example can be rewritten using class literals. The result is cleaner in many ways:<br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c10:PetCount2.java</font>
<font color=#009900>// Using class literals.</font>
<font color=#0000ff>package</font> c10;
<font color=#0000ff>import</font> com.bruceeckel.simpletest.*;
<font color=#0000ff>import</font> java.util.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> PetCount2 {
<font color=#0000ff>private</font> <font color=#0000ff>static</font> Test monitor = <font color=#0000ff>new</font> Test();
<font color=#0000ff>private</font> <font color=#0000ff>static</font> Random rand = <font color=#0000ff>new</font> Random();
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Object[] pets = <font color=#0000ff>new</font> Object[15];
Class[] petTypes = {
<font color=#009900>// Class literals:</font>
Pet.<font color=#0000ff>class</font>,
Dog.<font color=#0000ff>class</font>,
Pug.<font color=#0000ff>class</font>,
Cat.<font color=#0000ff>class</font>,
Rodent.<font color=#0000ff>class</font>,
Gerbil.<font color=#0000ff>class</font>,
Hamster.<font color=#0000ff>class</font>,
};
<font color=#0000ff>try</font> {
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < pets.length; i++) {
<font color=#009900>// Offset by one to eliminate Pet.class:</font>
<font color=#0000ff>int</font> rnd = 1 + rand.nextInt(petTypes.length - 1);
pets[i] = petTypes[rnd].newInstance();
}
} <font color=#0000ff>catch</font>(InstantiationException e) {
System.out.println(<font color=#004488>"Cannot instantiate"</font>);
System.exit(1);
} <font color=#0000ff>catch</font>(IllegalAccessException e) {
System.out.println(<font color=#004488>"Cannot access"</font>);
System.exit(1);
}
AssociativeArray map =
<font color=#0000ff>new</font> AssociativeArray(petTypes.length);
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < petTypes.length; i++)
map.put(petTypes[i].toString(), <font color=#0000ff>new</font> Counter());
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < pets.length; i++) {
Object o = pets[i];
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Pet)
((Counter)map.get(<font color=#004488>"class c10.Pet"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Dog)
((Counter)map.get(<font color=#004488>"class c10.Dog"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Pug)
((Counter)map.get(<font color=#004488>"class c10.Pug"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Cat)
((Counter)map.get(<font color=#004488>"class c10.Cat"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Rodent)
((Counter)map.get(<font color=#004488>"class c10.Rodent"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Gerbil)
((Counter)map.get(<font color=#004488>"class c10.Gerbil"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Hamster)
((Counter)map.get(<font color=#004488>"class c10.Hamster"</font>)).i++;
}
<font color=#009900>// List each individual pet:</font>
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < pets.length; i++)
System.out.println(pets[i].getClass());
<font color=#009900>// Show the counts:</font>
System.out.println(map);
monitor.expect(<font color=#0000ff>new</font> Object[] {
<font color=#0000ff>new</font> TestExpression(<font color=#004488>"%% class c10\\."</font> +
<font color=#004488>"(Dog|Pug|Cat|Rodent|Gerbil|Hamster)"</font>,
pets.length),
<font color=#0000ff>new</font> TestExpression(<font color=#004488>"%% class c10\\."</font> +
<font color=#004488>"(Pet|Dog|Pug|Cat|Rodent|Gerbil|Hamster) : \\d+"</font>,
petTypes.length)
});
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>Here, the <b>typenames</b> array has been removed in favor of getting the type name strings from the <b>Class</b> object. Notice that the system can distinguish between classes and interfaces. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap12_1852" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>You can also see that the creation of <b>petTypes</b> does not need to be surrounded by a <b>try</b> block since it’s evaluated at compile time and thus won’t throw any exceptions, unlike <b>Class.forName( )</b>. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap12_1853" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>When the <b>Pet</b> objects are dynamically created, you can see that the random number is restricted so it is between one and <b>petTypes.length</b> and does not include zero. That’s because zero refers to <b>Pet.class</b>, and presumably a generic <b>Pet</b> object is not interesting. However, since <b>Pet.class</b> is part of <b>petTypes</b>, the result is that all of the pets get counted. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap12_1854" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h4>
<a name="Heading9871"></a>A dynamic <b>instanceof</b><br></h4>
<p><a name="Index911"></a>The <b>Class.isInstance</b><a name="Index912"></a><a name="Index913"></a><a name="Index914"></a> method provides a way to dynamically call the <b>instanceof</b> operator. Thus, all those tedious <b>instanceof</b> statements can be removed in the <b>PetCount</b> example:<br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c10:PetCount3.java</font>
<font color=#009900>// Using isInstance()</font>
<font color=#0000ff>package</font> c10;
<font color=#0000ff>import</font> com.bruceeckel.simpletest.*;
<font color=#0000ff>import</font> java.util.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> PetCount3 {
<font color=#0000ff>private</font> <font color=#0000ff>static</font> Test monitor = <font color=#0000ff>new</font> Test();
<font color=#0000ff>private</font> <font color=#0000ff>static</font> Random rand = <font color=#0000ff>new</font> Random();
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Object[] pets = <font color=#0000ff>new</font> Object[15];
Class[] petTypes = {
<font color=#009900>// Class literals:</font>
Pet.<font color=#0000ff>class</font>,
Dog.<font color=#0000ff>class</font>,
Pug.<font color=#0000ff>class</font>,
Cat.<font color=#0000ff>class</font>,
Rodent.<font color=#0000ff>class</font>,
Gerbil.<font color=#0000ff>class</font>,
Hamster.<font color=#0000ff>class</font>,
};
<font color=#0000ff>try</font> {
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < pets.length; i++) {
<font color=#009900>// Offset by one to eliminate Pet.class:</font>
<font color=#0000ff>int</font> rnd = 1 + rand.nextInt(petTypes.length - 1);
pets[i] = petTypes[rnd].newInstance();
}
} <font color=#0000ff>catch</font>(InstantiationException e) {
System.out.println(<font color=#004488>"Cannot instantiate"</font>);
System.exit(1);
} <font color=#0000ff>catch</font>(IllegalAccessException e) {
System.out.println(<font color=#004488>"Cannot access"</font>);
System.exit(1);
}
AssociativeArray map =
<font color=#0000ff>new</font> AssociativeArray(petTypes.length);
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < petTypes.length; i++)
map.put(petTypes[i].toString(), <font color=#0000ff>new</font> Counter());
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < pets.length; i++) {
Object o = pets[i];
<font color=#009900>// Using Class.isInstance() to eliminate</font>
<font color=#009900>// individual instanceof expressions:</font>
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> j = 0; j < petTypes.length; ++j)
<font color=#0000ff>if</font>(petTypes[j].isInstance(o))
((Counter)map.get(petTypes[j].toString())).i++;
}
<font color=#009900>// List each individual pet:</font>
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < pets.length; i++)
System.out.println(pets[i].getClass());
<font color=#009900>// Show the counts:</font>
System.out.println(map);
monitor.expect(<font color=#0000ff>new</font> Object[] {
<font color=#0000ff>new</font> TestExpression(<font color=#004488>"%% class c10\\."</font> +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -