java 向下转型运行时错误_java 类型转换与编译错误,运行时错误 | 学步园

在特定的情况下,我们可以把子类转换成父类的“实例”,这就是向上转型;相反,我们也可以把父类转换成子类的“实例”,这就是向下转型。向上转型是安全的,向下转型则不然。

假设我们有三个类: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,运行时将会出现错误。

总结:

关于强制类型转换, 一共有两种类型的强制类型转换:

A) 向上类型转换(upcast):比如说将Cat类型转换为animal类型,即将子类型转换为父类型。对于向上类型转换,不需要显式指定。

B) 向下类型转换(downcast):比如将animal类型转换为cat类型。即将父类型转换为子类型,对于向下类型转换,必须要显式指定(必须要使用强制类型转换)。不是什么父类型都可以向下转换的,要看这个父类型变量具体指向的是什么对象。

为什么要使用向下类型转换?为了使用子类中特有的方法和属性,按照继承,父类中有的子类中一定有,子类中可以增加新的和修改原有的,而如果使用父类型指向一个子类型对象,就不能使用子类中的新增方法等。

public class PolyTest3

{

publicstatic void main(String[] args)

{

/*

Animal animal = new Cat();

Animal animal2 = new Animal();

animal2 =animal;

//animal和animal2都是Animal类型变量,同种变量类型可以相互赋值

//animal2由原来的指向Animal对象改为指向Cat对象

animal2.run();

//打印结果为cat is run

*/

/*

Animal animal = new Cat();

Animal animal2 = new Animal();

animal =animal2;

//animal和animal2都是Animal类型变量,同种变量类型可以相互赋值

//animal由原来的指向Cat对象改为指向Animal对象

animal.run();

//打印结果为animal is run

*/

Cat cat = new Cat();

Animal animal = cat;

//animal和cat是不同类型的类型变量,将Cat类型变量赋值给Animal类型变量

//animal指向Cat对象,父类型变量指向子类型对象

animal.run();

//打印结果为子类型方法结果:cat is run

/*

Animal animal = new Animal();

Cat cat = (Cat)animal;

//编译通过,运行错误,

*/

//向上类型转换

Cat cat =new Cat();

Animal animal = (Animal)cat;

//这里(Animal)cat是向上类型转换,可以不显示转换直接写cat

animal.run();

//向下类型转换

Animal a =new Cat();

//Cat cat =a;这样写不行,这样写就是说父类就是子类

Cat c =(Cat)a;

c.run();

}

}

class Animal

{

publicvoid run()

{

System.out.println("animal is run");

}

}

class dog extends Animal

{

publicvoid run()

{

System.out.println("dog is run");

}

}

class Cat extends Animal

{

publicvoid run()

{

System.out.println("cat is run");

}

}

参考:

感谢金丝燕大学校长

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值