通常意义上讲,子类都是可以强转成父类。父类不能强转成子类。但不是绝对!
通俗易懂地理解:1、儿子成年后通常都比父亲拥有更多的知识,通过儿子可以获取父亲的知识,但通过父亲不能获取儿子知识。
因此,正确:Father father =(Father) new Son();
错误:Son son=(Son) new Father();
结论:父亲不能转换为知识更丰富的儿子
2、什么情况下父类可以转换为子类?
Father father =(Father) new Son();
Son son=(Son) father ;
上面运行后是正确的,为啥?第一行Father father =(Father) new Son();并不是真正把儿子转换成了父亲,Father father像一个类型蒙板,指向的仍然是儿子,只是挡住了儿子部分的知识,只能显示父亲的知识。通过第二行Son son=(Son) father 后,还原了儿子的全部知识。
结论:不能光看前面类型是父类,前面只是类型蒙板。要看后面的实例是不是子类。
3、子类重写父类方法的理解
如果Son重写了Father的某个方法:儿子将父亲的某个知识点修正了。
再通过Father father =(Father) new Son();观察或应用那个修正的知识点会是啥情况?当然是修正后的知识点,父亲错误的知识点看不到了。
结论:前面类的类型只是类型蒙板,后面藏的改成啥样前面看到的才是啥样。
对于类的申明的最终理解:1、申明了一个类型蒙板;2、申明了一个指向真正实体的地址。(如:Father father)
public class Study {
public static void main(String[] args) {
/*
Father声明=Son实例
*/
//father1相当于蒙板,只保留Father相关的所有方法和变量,地址实际指向的仍然是Son实例
Father father1 = new Son(999);
//father1实际指向的是Son实例,通过蒙板(Son)转换访问全部Son实例
Son son1 = (Son) father1;
son1.sonMethod();
/*
Father声明=Father实例
*/
Father father2 = new Father();
//father2实际指向的是Father实例,通过蒙板(Son)转换只能访问father实例,
//无法访问子类信息,所以运行会报错。
Son son2 = (Son) father2;
son2.sonMethod();
}
static class Father {
Integer fatherInt;
public void fatherMethod() {
System.out.println("父类方法");
}
}
static class Son extends Father {
Integer sonInt;
public Son(Integer sonInt) {
this.sonInt = sonInt;
}
public void sonMethod() {
System.out.println("子类方法及子类的变量值:" + sonInt);
}
}
}