您的位置:首页 > 编程语言 > Java开发

java 类型转换与编译错误,运行时错误

2014-07-10 20:21 363 查看
在特定的情况下,我们可以把子类转换成父类的“实例”,这就是向上转型;相反,我们也可以把父类转换成子类的“实例”,这就是向下转型。向上转型是安全的,向下转型则不然。

假设我们有三个类: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");
}
}

参考:

http://blog.csdn.net/kaoa000/article/details/8308700

http://blog.csdn.net/zhu_apollo/article/details/1903374

http://blog.csdn.net/shanghui815/article/details/6088588

http://www.java3z.com/cwbwebhome/article/article8/81157.html?id=2664

 http://www.cnblogs.com/fickleness/archive/2013/06/21/3149011.html

感谢金丝燕大学校长
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐