向上转型会丢失子类多余父类的那部分方法;向下转型分为两种,一种是通过子类b向上转换为父类a,然后又由a向下转换为子类,这种完全可以通过编译和运行;而另外一种是先通过父类创建父类对象,然后由父类向下转换为子类,这种编译正确,但是会抛出运行时异常:java.lang.ClassCastException.
如下是一个综合例子说明:

1 package com.test.a; 2 3 public class Base { 4 public void f() 5 { 6 System.out.println("Base.f"); 7 } 8 9 }

1 package com.test.a; 2 3 public class Sub extends Base{ 4 public void f() 5 { 6 System.out.println("Sub.f"); 7 } 8 9 public void f2() 10 { 11 System.out.println("Sub.f2"); 12 } 13 14 }

1 package com.test.a; 2 3 public class Test { 4 public static void main(String args[]) { 5 //******向上转型**************** 6 Base base1=new Sub(); 7 base1.f();//print sub.f 8 // base1.f2();//compile error,因为sub比base多的那些方法在向上转型的过程中将要丢失 9 10 //********向下转型1******** 11 Sub sub1=(Sub)base1; 12 sub1.f();//print sub.f 13 sub1.f2();//print sub.f2 14 15 //********向下转型2********* 16 Base base2=new Base(); 17 Sub sub2=(Sub)base2;//ClassCastException 18 sub2.f();//ClassCastException 19 sub2.f2();//ClassCastException 20 } 21 22 }
为什么两种向下转型会有如此差异?这是因为前者base1指向了子类Sub的对象,所以子类Sub的实例对象当然也可以指向base1。而base2是一个父类对象,子类对象sub2不能指向父类对象base2。
那如何避免运行异常java.lang.ClassCastException,可以采用instanceof来避免:

1 package com.test.a; 2 3 public class Test { 4 public static void main(String args[]) { 5 //******向上转型**************** 6 Base base1=new Sub(); 7 base1.f();//print sub.f 8 // base1.f2();//compile error,因为sub比base多的那些方法在向上转型的过程中将要丢失 9 10 //********向下转型1******** 11 Sub sub1=(Sub)base1; 12 sub1.f();//print sub.f 13 sub1.f2();//print sub.f2 14 15 //********向下转型2********* 16 Base base2=new Base(); 17 if(base2 instanceof Sub) 18 { 19 Sub sub2=(Sub)base2;//ClassCastException 20 sub2.f();//ClassCastException 21 sub2.f2();//ClassCastException 22 } 23 24 } 25 26 }
向上转型的好处,比如可以在方法参数中只传入父类的引用,而具体是哪个子类还是父类对象交给编译器自己决定----后期绑定,减小代码的复杂啦。父类可以提供好更多可能的接口供子类使用;向下转型的好处,比如泛型机制的引入,这样就可以避免stiring和integer类型都加入了list,最终类型转换时报错。