14.1 为什么需要RTTI
运行时类型信息使得你可以在程序运行时发现和使用类型信息。
RTTI的意义:在运行中,动态地对引用指向的对象进行判断。作出对其适合的操作。
例如在实现多态特性实现的时候,对于只要求传入父类参数或接口的方法,对于传入的参数动态判断其属于哪个子类,并调用对应合适的方法。
14.2 Class对象
每一个类都有一个Class对象,JVM通过这个Class对象生成对应类的实例。
获得class对象的方法:1. Class.forName(“类名”)。2. 已知对象,直接调用其getClass方法。3. 类字面常量,类名.class或类名.TYPE。
java程序在需要时才加载对应类文件。单纯调用类的.class对象或编译期常量并不会触发类的初始化。
泛化的Class引用,通过泛型来控制Class引用的类型。
public class Demo {
public static void main(String[] args) {
Class c1 = Integer.class;
Class<Integer> c2 = Integer.class;
c1 = int.class;
c2 = int.class;
c1 = double.class;
//报错:Type mismatch: cannot convert from Class<Double> to Class<Integer>
c2 = double.class;
}
}
14.3 类型转换前先做检查
使用instanceof关键字,比较一个对象是否属于一个类。
public class Demo {
public static void main(String[] args) {
Integer i = 1;
Object o = null;
System.out.println(o instanceof Integer);//false
System.out.println(i instanceof Object);//true
}
}
instanceof 后似乎必须跟类名,不能以例如i.getClass()等方式获取类名。
使用类的isinstance()方法,动态地判定一个类是否为传入参数的类。
public class Demo {
public static void main(String[] args) {
Class<Integer> i = Integer.class;
int in = 1;
System.out.println(i.isInstance(in));//true
}
}
ps: int.class == Integer.TYPE, int.class != Integer.class。
instanceof()和equals()的区别,对于前者,比较的类与对象为相同或继承关系时表示为true。对于后者,二者为一个类产生的对象是才表示为true。
14.6 反射:运行时的类信息
在编译阶段,未知类的信息时,想要获取类的全部信息,需要用到反射机制。
RTTI和反射的区别
RTTI:在编译阶段已知类的全部信息,同时编译生成.class文件。
反射:在运行阶段才知道类的具体信息。调用Class对象的getMethod()和getConstructors()动态获取类的信息的方法和构造函数。
调用setAccessible(true),打破分装,访问并修改私有对象。
14.8 空对象
为了避免防止重复测试对象是否为空,设置空对象。
空对象逻辑上为空,实际对象并不为null。
使用中讲空对象设为单例,其他对象若需判断确定是否为空,则直接利用RTTI与之比较。
空对象的好处:
避免出现 NullPointerException,避免反复判断对象是否为空。
可以根据实际环境为空对象添加与非空对象相似的性质。如Book有方法getName,NullBook依旧可以用对应的方法。而null不行。
更为主动的解决了对象为空的问题。