问:在类型转换时,引用对象的类型是它所属的类,还是它所指的类?
答:对象的类型只有一个,就是调用它的 getClass() 方法获得的类型。在被引用时,引用它的变量可以是该类型,也可以是该类型的父类。例如一个 Integer 对象,引用它的变量可以是 Integer 类型,也可以是它的父类 Number 类型,甚至就是 Object 也可以。
问:在以下代码中:
Class T1 {}
Class T2 extends T1 {}
Class T3 extends T2 {}
Class Test {
public static void main(String [ ] args) {
T1 t1=new T3();
T2 t2=(T2)t1; //在类型转换时,是由T1向T2转换,还是由T3向T2转换?
//因此,它是不是强制转换呢?
}
}
答:t1 是一个变量,这个变量的类型是 T1;t1 指向一个对象,这个对象的类型是 T3。t2 是一个变量,这个变量的类型是 T2;t2 指向一个对象,这个对象同样是 t1 指向的对象。所以这个类型转换实际上是将 T3 类型的对象引用为 T2 类型。
问:因此,它是向上提升了,所以不是强制转换是吗?
答:可以这么理解,因为所有的强制类型转换是在继承链中转换。例如:Object<-Comparable<-Date<-Timestamp 这个继承链,对于任何一个 Timestamp 对象,你可以将指向它的变量强制转换为 Object、Comparable 或 Date 类型而不会出错;但如果强制转换为其他类型,如 String,就会出错了。
问:不是说向上转换都是自动转换吗?
答:是的,向上转换不需要强制。不管向上向下,其实都不过是变量的类型和其指向的对象类型的匹配问题。
问:我还是不明白。那么在:
T1 t1=new T3();
T2 t2=(T2)t1;
中,第一句是自动转换我明白,它是由T3到T1;
第二句为什么是强制转换呢?不是从T3到T2吗?应该是自动转换啊?
答:变量的类型在它定义的时候就决定了,而与它实际指向的对象的类型无关。因为变量 t1 的类型是 T1,所以在编译时只能判定 t1 指向的是一个 T1 对象。虽然它在运行的某一时刻时指向一个 T3 对象,但不能因此把 t1 变量看成是 T3 类型的。
问:噢,我明白了,谢谢!