第十章: Detecting Types
run-time type identification (RTTI) 运行时类型识别-- It lets you find the exact type of an object when you have only a reference to the base type. This takes two forms: “Traditional” RTTI, which assumes that you have all the types available at compile time and run time, and the “reflection” mechanism, which allows you to discover class information solely at run time.
1、 The Class object—用来保存类的信息,程序里每个类都有一个class对象,它存在同名的.class文件里.
Class.forName("Gum");//运行时检查
Gum.class; //与上同,编译时检查,简单,效率更高也更安全。
Class类不但能用于普通类,还能用于接口、数组、primitive类型,此外每种primitive的
wrapper类还有一个标准的名为TYPE的数据成员,The TYPE field produces a reference to the Class object for the associated primitive type, such that:
... is equivalent to ... | |
boolean.class | Boolean.TYPE |
char.class | Character.TYPE |
byte.class | Byte.TYPE |
short.class | Short.TYPE |
int.class | Integer.TYPE |
long.class | Long.TYPE |
float.class | Float.TYPE |
double.class | Double.TYPE |
void.class | Void.TYPE |
2、RTTI forms including:
a) The classic cast经典的类型转换; e.g., “(Shape),” which uses RTTI to make sure the cast is correct. This will throw a ClassCastException if you’ve performed a bad cast.
b) The Class object representing the type of your object. The Class object can be queried for useful run time information.
c) the keyword instanceof.like this:
if(x instanceof Dog) //Dog.isInstance(x)
((Dog)x).bark();
instanceof vs. Class equivalence:
package c10;
import com.bruceeckel.simpletest.*;
class Base {}
class Derived extends Base {}
public class FamilyVsExactType {
private static Test monitor = new Test();
static void test(Object x) {
System.out.println("Testing x of type " +
x.getClass());
System.out.println("x instanceof Base " +
(x instanceof Base));
System.out.println("x instanceof Derived " +
(x instanceof Derived));
System.out.println("Base.isInstance(x) " +
Base.class.isInstance(x));
System.out.println("Derived.isInstance(x) " +
Derived.class.isInstance(x));
System.out.println("x.getClass() == Base.class " +
(x.getClass() == Base.class));
System.out.println("x.getClass() == Derived.class " +
(x.getClass() == Derived.class));
System.out.println("x.getClass().equals(Base.class)) "+
(x.getClass().equals(Base.class)));
System.out.println(
"x.getClass().equals(Derived.class)) " +
(x.getClass().equals(Derived.class)));
}
public static void main(String[] args) {
test(new Base());
test(new Derived());
monitor.expect(new String[] {
"Testing x of type class c10.Base",
"x instanceof Base true",
"x instanceof Derived false",
"Base.isInstance(x) true",
"Derived.isInstance(x) false",
"x.getClass() == Base.class true",
"x.getClass() == Derived.class false",
"x.getClass().equals(Base.class)) true",
"x.getClass().equals(Derived.class)) false",
"Testing x of type class c10.Derived",
"x instanceof Base true",
"x instanceof Derived true",
"Base.isInstance(x) true",
"Derived.isInstance(x) true",
"x.getClass() == Base.class false",
"x.getClass() == Derived.class true",
"x.getClass().equals(Base.class)) false",
"x.getClass().equals(Derived.class)) true"
});
}
} ///:~
2、 RTTI syntax
3、 Reflection: run time class information
the true difference between RTTI and reflection is that with RTTI, the compiler opens and examines the .class file at compile time. Put another way, you can call all the methods of an object in the “normal” way. With reflection, the .class file is unavailable at compile time; it is opened and examined by the run-time environment.经常用来支持一些别的特性,如:对象序列化、JavaBean、Remote Method Invocation (RMI).
3、 Reflection: run time class information
the true difference between RTTI and reflection is that with RTTI, the compiler opens and examines the .class file at compile time. Put another way, you can call all the methods of an object in the “normal” way. With reflection, the .class file is unavailable at compile time; it is opened and examined by the run-time environment.经常用来支持一些别的特性,如:对象序列化、JavaBean、Remote Method Invocation (RMI).