java 多态向上转型和向下转型
java对象的向上或是向下转型是多态的具体表现形式。多态:方法或对象具有多种形态,
多态是建立在封装和继承的基础之上的,所以多态的前提是:两个对象(类)必须存在继承关系。
1> 方法的多态: 重写或是重载就是方法的多态提现
2>对象的多态 :对象的编译类型与运行类型可以不一样的,
Animal animal = new Dog(); //animal编译类型就是Animal,animal运行类型是Dog
animal = new Pig() ; //animal的运行类型变成了Pig,编译类型仍然是Animal没有变
总结:
编译类型看定义时的 =号的左边,运行类型看定义时=的右边。
运行类型是可以变化的。
编译类型在定义对象时就确定了,无法再更改。
向上转型 : 通过子类对象(小范围)实例化父类对象(大范围),这种属于自动转换
向下转型 : 通过父类对象(大范围)实例化子类对象(小范围),这种属于强制转换
多态的向上转型:
本质:父类的引用指向子类的对象。
语法:父类类型 引用名 = new 子类类型();
编译类型看=号左边,运行类型看=号右边
上向转型后可以调用父类中的所有成员(仍需遵守访问权限,或父类的private方法子类肯定是不可能调用的),
不能再调用子类中的特有成员。
最终运行效果看子类的具体实现
属性没有重写(多态)之说,属性值看编译类型,即属性是哪个类文件中声明定义的,就使用那文件中的属性。
如base类与sub类中都定义了一个属性int arg ,父类中的值是1,子类中的值是10;
如是在父类中调用arg属性则使用父类中的arg=1,
如是在子类中调用arg属性则使用子类中的arg=10,
class Animal{ public void move(){ System.out.println("动物可以移动"); } } class Dog extends Animal{ public void move(){ System.out.println("狗可以跑和走"); } public void bark(){ System.out.println("狗可以吠叫"); } } public class TestDog{ public static void main(String args[]){ Animal a = new Animal(); // Animal 对象 Animal b = new Dog(); // Dog 对象 a.move();// 执行 Animal 类的方法 b.move();//执行 Dog 类的方法; b实际指向的是 Dog子类,所以调用时会调用子类本身的方法。 b.bark();//这里能编译通过,但执行时会报错,因为b对象会遗失与父类对象a共有方法外的其它方法 } } 以上实例编译运行结果如下: TestDog.java:30: cannot find symbol symbol : method bark() location: class Animal b.bark(); //报异常 该程序将抛出一个编译错误,因为b的引用类型Animal没有bark方法。 ^
PS:向上转型时子类Dog会遗失与父类对象共有方法外的的其他方法;
PS:向上转型时,父类只能调用父类方法或者子类覆写后的方法,而子类中的单独方法则是无法调用的()
向下转型
向下转型的前提是父类对象指向的是子类对象(也就是说,在向下转型之前,它得先向上转型)
在java中,向下转型则是为了,通过父类强制转换为子类,从而来调用子类中的所有方法,
语法: 子类类型 引用名 = (子类类型)父类引用;
父类的引用必须指向是当前目标类型的对象(即:要向下转型的对象类型)。
Animal a = new Dog(); Dog c = ((Dog) a); // 下面的代码编译无错但会运行会出错 Animal a1 = new Animal(); //只能强转父类的引用,不能强转父类的对象 Dog c1 = ((Dog) a1);
所以向下转型前要先用instanceof进行判断。
推荐文章:
https://www.cnblogs.com/xiaoyezideboke/p/10939219.html
https://www.cnblogs.com/lifexy/p/10812841.html
评论