声明一个父类Father,子类Son继承Father
Father a = new Son() // 父类引用、子类对象(向上转型) Son b = (Son)a // 向下转型,强制转换 // 父类引用转成子类引用
public class Animal { public void eat(){ System.out.println("animal eatting..."); } } class Bird extends Animal{ public void eat(){ System.out.println("bird eatting..."); } public void fly(){ System.out.println("bird flying..."); } } class Main{ public static void main(String[] args) { Animal b=new Bird(); //向上转型 b.eat(); // 调用的是子类eat() //! error: b.fly(); // b虽指向子类对象,但此时子类作为向上转型的代价丢失和父类不同的fly()方法------ dosleep(new Male()); dosleep(new Female()); } public static void dosleep(Human h) { h.sleep(); } }
public class Human { public void sleep() { System.out.println("Human sleep.."); } } class Male extends Human { @Override public void sleep() { System.out.println("Male sleep.."); } } class Female extends Human { @Override public void sleep() { System.out.println("Female sleep.."); } }
这里就可以看出向上转型的好处和使用场景了
public static void dosleep(Human h) { h.sleep(); }
这里的参数类型是父类,传入的值是子类,这就完成了向上转型操作。然后会自动判断调用该子类的对应方法。试想,如果我们这么干
public static void dosleep(Male male) { male.sleep(); } public static void dosleep(Female fe) { fe.sleep(); } ......
这是人,要换成水果,给你来个几百种,不写死才怪。
因此向上转型很好的简化了代码,也正是体现了java的抽象编程思想,使代码变得解耦。
class Fruit { public void myName() { System.out.println("我是父类 水果..."); } } class Apple extends Fruit { @Override public void myName() { System.out.println("我是子类 苹果..."); } public void myMore() { System.out.println("我是你的小呀小苹果~~~~~~"); } } public class Sys{ public static void main(String[] args) { Fruit a=new Apple(); //向上转型 a.myName(); Apple aa=(Apple)a; //向下转型,编译和运行皆不会出错(正确的) aa.myName();//向下转型时调用的是子类的 aa.myMore();; Fruit f=new Fruit(); Apple aaa=(Apple)f; //-不安全的---向下转型,编译无错但会运行会出错 aaa.myName(); aaa.myMore(); } }
输出:
解释:
- 正确的向下转型
Fruit a=new Apple(); //向上转型 a.myName(); Apple aa=(Apple)a; //向下转型,编译和运行皆不会出错(正确的) aa.myName();//向下转型时调用的是子类的
a指向子类的对象,所以子类的实例aa也可以指向a
向下转型后因为都是指向子类对象,所以调用的当然全是子类的方法
- 错误的向下转型
Fruit f=new Fruit(); Apple aaa=(Apple)f; //-不安全的---向下转型,编译无错但会运行会出错 aaa.myName(); aaa.myMore();
这里f指向父类对象,子类实例肯定不能指向f
3.Java为了解决不安全的向下转型问题,引入泛型的概念
4.为了安全的类型转换,最好先用 if(A instanceof B) 判断一下对象类型
例:
if (f instanceof Apple){ Apple aaa=(Apple)f; aaa.myName(); aaa.myMore(); }
参考文章:https://blog.csdn.net/sheepmu/article/details/38327205
来源:博客园
作者:Gyyyang
链接:https://www.cnblogs.com/gyyyblog/p/11806601.html