向上转型:
子类引用的对象转换为父类类型称为向上转型。通俗地说就是是将子类对象转为父类对象。此处父类对象可以是接口
1 public class Animal { 2 public void eat(){ 3 System.out.println("Animal eat!"); 4 } 5 } 6 7 class Bird extends Animal{ 8 public void eat(){ 9 System.out.println("Bird eat!"); 10 } 11 12 public void fly(){ 13 System.out.println("Bird fly!"); 14 } 15 } 16 17 class Main{ 18 public static void main(String[] args) { 19 Animal b = new Bird(); //向上转型 20 b.eat(); 21 b.fly(); //此处提示在Animal中没有定义fly方法。 22 } 23
在上面的例子里,Animal b = new Bird()就是一个典型的向上转型,子类对象当成父类对象,只能调用父类的成员,如果子类重写了父类的方法就根据这个引用指向调用子类重写的这个方法这个方法就是覆盖override)。这个调用过程就称为“动态绑定”。
需要注意的是,向上转型时,父类指向子类引用对象会遗失除与父类对象共有的其他方法,也就是在转型过程中,子类的新有的方法都会遗失掉,在编译时,系统会提供找不到方法的错误。在上例中b.fly()出现错误就是这个原因。
向下转型:
父类引用的对象转换为子类类型称为向下转型。
1 public class Person { 2 public void smile(){ 3 System.out.println("Person smile!"); 4 } 5 } 6 7 class Girl extends Person{ 8 public void smile() { 9 System.out.println("Girl smile!"); 10 } 11 12 public void sing(){ 13 System.out.println("Girl sing!"); 14 } 15 } 16 17 class main{ 18 public static void main(String[] args) { 19 Person person=new Girl(); //向上转型 20 person.smile(); 21 22 Girl girl=(Girl)person; //向下转型,编译和运行皆不会出错 23 girl.smile(); 24 girl.sing(); 25 26 Person person1=new Person(); 27 //Girl girl1=(Girl)person1; //不安全的向下转型,编译无错但会运行会出错 28 //girl1.smile(); 29 //girl1.sing(); 30 31 if(person1 instanceof Girl){ 32 Girl girl1=(Girl)person1; 33 girl1.smile(); 34 girl1.sing(); 35 } 36 }
在向下转型过程中,分为两种情况:
情况一:如果父类引用的对象引用的是指向的子类对象,那么在向下转型的过程中是安全的。也就是编译是不会出错误的。
情况二:如果父类引用的对象是父类本身,那么在向下转型的过程中是不安全的,编译不会出错,但是运行时会出现java.lang.ClassCastException错误。它可以使用instanceof来避免出错此类错误。
总结:
1、父类引用可以指向子类对象,子类引用不能指向父类对象。
2、把子类对象直接赋给父类引用叫向上转型,向上转型不用强制转型。
如Father father = new Son();
3、把指向子类对象的父类引用赋给子类引用叫向下转型,要强制转型。
如father就是一个指向子类对象的父类引用,把father赋给子类引用son 即Son son =(Son)father;
其中father前面的(Son)必须添加,进行强制转换。
4、向上转型会丢失子类特有的方法,但是子类重写父类的方法,子类方法有效;
5、向上转型的作用,减少重复代码,父类为参数,调有时用子类作为参数,就是利用了向上转型。这样使代码变得简洁。