(1)向上转型:
将子类对象转化为父类对象,通俗来说个人理解就是,就是通过父类对象执行子类对象中的方法等。
例子:
//父类
public class Transtation1 {
public void animal(){
System.out.println("在这里我还是动物");
}
}
//子类
public class Transtation2 extends Transtation1 {
public void animal(){
System.out.println("在这里我已经不是动物了");
}
public void bird(){
System.out.println("我是一只鸟");
}
public void cat(){
System.out.println("我是一只猫");
}
public void dog(){
System.out.println("我是一条狗");
}
}
//测试类
public class TranstationTest {
public static void main(String[] args) {
//向上转型
Transtation1 a = new Transtation2();
a.animal();
//需要注意的是向上转型时a会遗失除与父类对象共有的其他方法
//如a.bird() 这是不允许的,无法通过编译。虽然a指向了子类对象Transtation2,但是只能访问子类中与父类相同的方法。
}
}
输出结果:在这里我已经不是动物了
重点注意:向上转型的对象,只能访问子类中的与父类相同的方法,其他方法丢失。例如本例中,只能有a.animal()不能有a.bird(),即不能有子类的其他方法。
向上转型的好处:可以减少代码冗余。重新来一个猫和狗的例子,如下:
//父类
public class animail {
public void eat(){
System.out.println("我还不知道吃啥...");
}
}
//子类1
public class cat extends animail {
public void eat(){
System.out.println("我吃鱼");
}
}
//子类2
public class dog extends animail {
public void eat(){
System.out.println("我吃骨头");
}
}
使用了向上转型的测试类:
//测试类 使用了向上转型的测试类
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
animail c= new cat();
animail d =new dog();
eat(c);
eat(d);
}
//只需写一个方法
public static void eat(animail a){
a.eat();
}
}
未使用向上转型的测试类:
//测试类 未使用向上转型 这是不好的方式
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
cat c = new cat();
dog d = new dog();
eat(c);
eat(d);
}
//不用向上转型,就得写两个方法
public static void eat(cat a){
a.eat();
}
public static void eat(dog a){
a.eat();
}
}
两个测试类的输出结果都为:
我吃鱼
我吃骨头
两个测试类中的区别在哪里:虽然都达到了一样的效果,但是代码实现不一样,在使用了向上转型的类中,我们只需要写一次eat(animal a)方法,其中的参数是父类animal a,在每次增加一个动物的时候,我们无需再写eat()方法。但是。如过按照测试类2,每增加一个动物都要多写一次eat()方法,之多一个好说,那突然多了10000种动物呢?结果不言而喻。
(2)向下转型:
向下转型通俗来讲就是把父类对象转化为子类对象:
例如:更改测试类中的代码为如下代码
1)安全的向下转型
//测试类
public class TranstationTest {
public static void main(String[] args) {
//向上转型
Transtation1 a = new Transtation2();
a.animal();
//需要注意的是向上转型时a会遗失除与父类对象共有的其他方法
//如a.bird() 这是不允许的,无法通过编译。虽然a指向了子类对象Transtation2,但是只能访问子类中与父类相同的方法。
//安全的向下转型
Transtation2 b = (Transtation2) a;
b.animal();
b.bird();
}
}
输出结果:
在这里我已经不是动物了
在这里我已经不是动物了
我是一只鸟
2)不安全的向下转型
//测试类
public class TranstationTest {
public static void main(String[] args) {
//不安全的向下转型,并以不会报错,但执行时报错
Transtation1 c = new Transtation1();
Transtation2 d = (Transtation2) c;
d.animal();
d.bird();
}
}
运行报错:Exception in thread "main" java.lang.ClassCastException: com.test.zy726.Transtation1 cannot be cast to com.test.zy726.Transtation2
at com.test.zy726.TranstationTest.main(TranstationTest.java:18)
是不是依旧不怎么懂,那来个更加形象的例子,还是前面猫和狗的例子,这是他们的一个测试类:
//测试1
public class TestDogAndCat {
public static void main(String[] args) {
//先向上转型,再向下转型
animail a =new cat();
cat c = (cat) a;
c.eat();
}
//执行结果是:我吃鱼
//测试2
public class TestDogAndCat {
public static void main(String[] args) {
//先向上转型再向下
animail a =new cat();
dog d = (dog) a;
d.eat();
}
}
//执行结果是啥?你以为会是:我吃骨头吗?当然不是
//它是无法执行的
//报错异常:Exception in thread "main" java.lang.ClassCastException: com.test.zy726.cat cannot be cast to com.test.zy726.dog
at com.test.zy726.TestDogAndCat.main(TestDogAndCat.java:11)
分析:为啥测试1可以,测试2就不行了?因为,a本来就已经是个猫的对象了,你在测试2里面你想把它变成狗吗?
public class TestDogAndCat {
public static void main(String[] args) {
//向上转型
animail a =new animail();
dog d = (dog) a;
d.eat();
}
}
//这样可以吗?不可以
//运行结果,抛出异常:Exception in thread "main" java.lang.ClassCastException: com.test.zy726.animail cannot be cast to com.test.zy726.dog
at com.test.zy726.TestDogAndCat.main(TestDogAndCat.java:11)
分析:为啥呢,你去考古发现了一个几千年前的动物,你就能直接说,哦,这个动物是狗?
向下转型总结:
(a)向下转型的前提是父类对象指向的是子类对象(也就是说,在向下转型之前,它得先向上转型)
(b)向下转型只能转型为本类对象(猫是不能变成狗的)。