在特定的情况下,我们可以把子类转换成父类的“实例”,这就是向上转型;相反,我们也可以把父类转换成子类的“实例”,这就是向下转型。向上转型是安全的,向下转型则不然。
假设我们有三个类:bird,parrot,swallow,后两个类继承了bird类。
我们使用Bird b = p这个语句将p转型为bird的一个实例。然后,当调用b.fly()时,实际上调用的仍然是bird的fly()方法;但是当调用b.eat时,实际上调用的parrot的方法eat方法,而不是bird的eat方法。另外,当p转型为bird后,由于bird没有say方法,那么b.say方法不可用。
假设我们有三个类:bird,parrot,swallow,后两个类继承了bird类。
向上转型
class Bird {
public void fly()
{
System.out.println("Bird.fly()");
}
public void eat()
{
System.out.println("Bird.eat()");
}
}
class Parrot extends Bird{
public void eat()
{
System.out.println("Parrot.eat()");
}
public void say()
{
System.out.println("Parrot.say()");
}
}
class Swallow extends Bird{
public void eat()
{
System.out.println("Swallow.eat()");
}
public void sleep()
{
System.out.println("Swallow.sleep()");
}
}
public class Main{
public static void main(String args[])
{
Main main = new Main();
main.upcast();
}
public void upcast()
{
Parrot p = new Parrot();
p.fly();
p.say();
p.eat();
Bird b = p;
b.fly();
b.eat();
//b.say(); 转型成Bird后,say方法不可见
}
}
结果为:
Bird.fly()
Parrot.say()
Parrot.eat()
Bird.fly()
Parrot.eat()
Bird类有一个fly方法,子类parrot和swallow都可以使用它;bird有一个eat方法,子类parrot和swallow覆盖了整个方法;子类parrot增加了一个say方法,子类swallow增加了一个sleep方法。
我们使用Bird b = p这个语句将p转型为bird的一个实例。然后,当调用b.fly()时,实际上调用的仍然是bird的fly()方法;但是当调用b.eat时,实际上调用的parrot的方法eat方法,而不是bird的eat方法。另外,当p转型为bird后,由于bird没有say方法,那么b.say方法不可用。
向下转型
public class Main2 {
public static void main(String[] args)
{
Main2 main = new Main2();
main.downcast();
main.downcastError();
}
public void downcast()
{
System.out.println("如果这样向下转型,将不会产生错误");
Bird b = new Parrot();
Parrot p = (Parrot)b;
p.fly();
}
public void downcastError()
{
System.out.println("如果这样向下转型,将会产生错误");
Bird b = new Bird();
Parrot p = (Parrot)b;
p.fly();
}
}
第一种转型方法之所以能够顺利进行,是因为bird b本来就是一个parrot实例,我们把它转回去,当然不会出错。
混合转型
public class Main3 {
public static void main(String[] args) {
Main3 main = new Main3();
main.multcast();
}
public void multcast()
{
Bird b;
Parrot p = new Parrot();
Swallow s;
//s = (Swallow)p;编译错误
b = (Bird)p;
b.eat();
s = (Swallow)b;//编译顺利,运行错误0
s.eat();
}
}
如果我们直接使用s = (Swallow)p进行转型,那么在编译时就会产生错误。但是如果先把一个parrot的实例转换成bird,然后再把bird转换成swallow,运行时将会出现错误。
感谢金丝燕大学校长