📄 tij312.htm
字号:
<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>You can see that the <b>isInstance( )</b> method has eliminated the need for the <b>instanceof</b> expressions. In addition, this means that you can add new types of pets simply by changing the <b>petTypes</b> array; the rest of the program does not need modification (as it did when using the <b>instanceof</b> expressions). <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap12_1855" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h4>
<a name="Heading9936"></a><b>instanceof</b> vs. <b>Class</b>
equivalence<br></h4>
<p><a name="Index915"></a>When querying for type information, there’s an important difference between either form of <b>instanceof</b> (that is, <b>instanceof</b> or <b>isInstance( )</b>, which produce equivalent results) and the direct comparison of the <b>Class</b> objects. Here’s an example that demonstrates the difference:<br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c10:FamilyVsExactType.java</font>
<font color=#009900>// The difference between instanceof and class</font>
<font color=#0000ff>package</font> c10;
<font color=#0000ff>import</font> com.bruceeckel.simpletest.*;
<font color=#0000ff>class</font> Base {}
<font color=#0000ff>class</font> Derived <font color=#0000ff>extends</font> Base {}
<font color=#0000ff>public</font> <font color=#0000ff>class</font> FamilyVsExactType {
<font color=#0000ff>private</font> <font color=#0000ff>static</font> Test monitor = <font color=#0000ff>new</font> Test();
<font color=#0000ff>static</font> <font color=#0000ff>void</font> test(Object x) {
System.out.println(<font color=#004488>"Testing x of type "</font> +
x.getClass());
System.out.println(<font color=#004488>"x instanceof Base "</font> +
(x <font color=#0000ff>instanceof</font> Base));
System.out.println(<font color=#004488>"x instanceof Derived "</font> +
(x <font color=#0000ff>instanceof</font> Derived));
System.out.println(<font color=#004488>"Base.isInstance(x) "</font> +
Base.<font color=#0000ff>class</font>.isInstance(x));
System.out.println(<font color=#004488>"Derived.isInstance(x) "</font> +
Derived.<font color=#0000ff>class</font>.isInstance(x));
System.out.println(<font color=#004488>"x.getClass() == Base.class "</font> +
(x.getClass() == Base.<font color=#0000ff>class</font>));
System.out.println(<font color=#004488>"x.getClass() == Derived.class "</font> +
(x.getClass() == Derived.<font color=#0000ff>class</font>));
System.out.println(<font color=#004488>"x.getClass().equals(Base.class)) "</font>+
(x.getClass().equals(Base.<font color=#0000ff>class</font>)));
System.out.println(
<font color=#004488>"x.getClass().equals(Derived.class)) "</font> +
(x.getClass().equals(Derived.<font color=#0000ff>class</font>)));
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
test(<font color=#0000ff>new</font> Base());
test(<font color=#0000ff>new</font> Derived());
monitor.expect(<font color=#0000ff>new</font> String[] {
<font color=#004488>"Testing x of type class c10.Base"</font>,
<font color=#004488>"x instanceof Base true"</font>,
<font color=#004488>"x instanceof Derived false"</font>,
<font color=#004488>"Base.isInstance(x) true"</font>,
<font color=#004488>"Derived.isInstance(x) false"</font>,
<font color=#004488>"x.getClass() == Base.class true"</font>,
<font color=#004488>"x.getClass() == Derived.class false"</font>,
<font color=#004488>"x.getClass().equals(Base.class)) true"</font>,
<font color=#004488>"x.getClass().equals(Derived.class)) false"</font>,
<font color=#004488>"Testing x of type class c10.Derived"</font>,
<font color=#004488>"x instanceof Base true"</font>,
<font color=#004488>"x instanceof Derived true"</font>,
<font color=#004488>"Base.isInstance(x) true"</font>,
<font color=#004488>"Derived.isInstance(x) true"</font>,
<font color=#004488>"x.getClass() == Base.class false"</font>,
<font color=#004488>"x.getClass() == Derived.class true"</font>,
<font color=#004488>"x.getClass().equals(Base.class)) false"</font>,
<font color=#004488>"x.getClass().equals(Derived.class)) true"</font>
});
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>The <b>test( )</b> method performs type checking with its argument using both forms of <b>instanceof</b>. It then gets the <b>Class</b> reference and uses <b>==</b> and <b>equals( ) </b>to test for equality of the <b>Class</b> objects. Reassuringly, <b>instanceof </b>and <b>isInstance( )</b> produce exactly the same results, as do <b>equals( )</b> and <b>==</b>. But the tests themselves draw different conclusions. In keeping with the concept of type, <b>instanceof</b> says “are you this class, or a class derived from this class?” On the other hand, if you compare the actual <b>Class</b> objects using <b>==</b>, there is no concern with inheritance—it’s either the exact type or it isn’t. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap12_1856" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h2>
<a name="_Toc305593313"></a><a name="_Toc305628785"></a><a name="_Toc312374146"></a><a name="_Toc375545409"></a><a name="_Toc375545407"></a><a name="_Toc24775728"></a><a name="Heading9996"></a>RTTI
syntax</h2>
<p>Java performs its RTTI using the <a name="Index916"></a><a name="Index917"></a><b>Class</b> object, even if you’re doing something like a cast. The class <b>Class</b> also has a number of other ways you can use RTTI. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap12_1857" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>First, you must get a reference to the appropriate <b>Class</b> object. One way to do this, as shown in the previous example, is to use a string and the <b>Class.forName( )</b> method. This is convenient because you don’t need an object of that type in order to get the <b>Class</b> reference. However, if you do already have an object of the type you’re interested in, you can fetch the <b>Class</b> reference by calling a method that’s part of the <b>Object</b> root class:<b> </b><a name="Index918"></a><a name="Index919"></a><b>getClass( )</b>. This returns the <b>Class</b> reference representing the actual type of the object. <b>Class</b> has many interesting methods demonstrated in the following example: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0493" title="Send BackTalk Comment">Feedback</a></font><br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c10:ToyTest.java</font>
<font color=#009900>// Testing class Class.</font>
<font color=#0000ff>import</font> com.bruceeckel.simpletest.*;
<font color=#0000ff>interface</font> HasBatteries {}
<font color=#0000ff>interface</font> Waterproof {}
<font color=#0000ff>interface</font> Shoots {}
<font color=#0000ff>class</font> Toy {
<font color=#009900>// Comment out the following default constructor</font>
<font color=#009900>// to see NoSuchMethodError from (*1*)</font>
Toy() {}
Toy(<font color=#0000ff>int</font> i) {}
}
<font color=#0000ff>class</font> FancyToy <font color=#0000ff>extends</font> Toy
<font color=#0000ff>implements</font> HasBatteries, Waterproof, Shoots {
FancyToy() { <font color=#0000ff>super</font>(1); }
}
<font color=#0000ff>public</font> <font color=#0000ff>class</font> ToyTest {
<font color=#0000ff>private</font> <font color=#0000ff>static</font> Test monitor = <font color=#0000ff>new</font> Test();
<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=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
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.out.println(<font color=#004488>"Can't find FancyToy"</font>);
System.exit(1);
}
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.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);
}
printInfo(o.getClass());
monitor.expect(<font color=#0000ff>new</font> String[] {
<font color=#004488>"Class name: FancyToy is interface? [false]"</font>,
<font color=#004488>"Class name: HasBatteries is interface? [true]"</font>,
<font color=#004488>"Class name: Waterproof is interface? [true]"</font>,
<font color=#004488>"Class name: Shoots is interface? [true]"</font>,
<font color=#004488>"Class name: Toy is interface? [false]"</font>
});
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>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 <b>HasBatteries</b>, <b>Waterproof</b>, and <b>Shoots</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. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap12_1858" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>The <b>Class.getInterfaces( )</b> method returns an array of <a name="Index920"></a><a name="Index921"></a><b>Class</b> objects representing the interfaces that are contained in the <b>Class</b> object of interest. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap12_1859" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>If you have a <b>Class</b> object, you can also ask it for its direct base class using <a name="Index922"></a><a name="Index923"></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. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap12_1860" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>The <a name="Index924"></a><a name="Index925"></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 preceding example, <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 (Application Programmer Interface). <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap12_1861" title="Send BackTalk Comment">Feedback</a></font
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -