昨天遇见一道笔试题,大意是给定如下代码,问编译运行有没有错:
public class Solution {
public static void main(String[] args) {
Father father = new Father();
Child child = (Child) father;
}
}
class Father {}
class Child extends Father {}
没仔细看直接选了「编译运行正常」。
交卷后测试了一下发现结果却是:
Exception in thread "main" java.lang.ClassCastException: Father cannot be cast to Child
其实细想一下,子类的内容是大于等于父类的,把父类转成子类,将来需要调用子类特有的方法,那不是逻辑冲突了吗。所以以上代码「编译正常,运行出错」。
反过来说,子类转父类是完全可以,不过这是一种损失精度的转变。看下面这段代代码:
public class Solution {
public static void main(String[] args) {
Child child = new Child();
Father father = (Father) child;
father.fMethod();
father.cMethod(); // compile error
}
}
class Father {
public void fMethod(){
System.out.println("father's method");
}
}
class Child extends Father {
public void cMethod(){
System.out.println("child's method");
}
}
子类转成父类之后,损失了自己特有的方法 cMethod()
,只能调用父类的方法 fMethod()
。
那么是不是父类对象一定不能转成子类对象,看看下面这种特殊的形式:
public class Solution {
public static void main(String[] args) {
Father father = new Child();
Child child = (Child) father;
child.cMethod();
child.fMethod();
}
}
class Father {
public void fMethod() {
System.out.println("father's method");
}
}
class Child extends Father {
public void cMethod() {
System.out.println("child's method");
}
}
在这个示例代码中,father
实际上父类引用指向子类对象,它实际上还是一个 Child
对象 ,所以这里转换是完全没有问题的。不会报错,也不会损失精度。
其实说白了,在判断父类对象能不能转化为子类对象的时候,只要判断父类对象是不是一个子类对象就可以了,反映到代码上就是 father instanceof Child
,如果是,可以转;不是,不可以转。
PREVIOUS江山
NEXT线程安全的单例模式的几种实现方式