前言
今天继续Java面向对象的学习,学习面向对象的第三大特征:多态,了解多态的意义,以及两种引用类型之间的转换:向上转型、向下转型。
希望能对你的学习有所帮助!
提示:以下是本篇文章正文内容,Java系列学习将会持续更新
一、多态
(1)基本概念
多态就是指一个引用可以表示多种状态。意义在于实现参数统一化。
饮料:可乐、雪碧、红牛、美年达、…
宠物:狗、猫、鸟、…
整数: byte b = 10; short s = 10; int i = 10;…
C++多态分为两种:编译多态、运行时多态
Java的多态只有一种,就是运行时多态。是一种运行期间的行为,而不是编译期的行为。
(2)语法格式
父类类型 引用 = new 子类类型();
Person ps = new Student();
ps.show();
解析:
在编译阶段ps是Person类型,因此调用Person类自己的show()方法,若没有则编译的时候就报错。
在运行阶段ps真正指向的对象是Student类型,因此最终调用的是Student类中自己的show()方法。
当使用多态方式调用方法的时候,首先会检查父类中是否有该方法,如果没有,则编译报错。
如果有,再去调用子类的同名方法。(注意:静态static方法属于特殊情况,静态方法只能继承,不能重写override,如果子类中定义了同名同形式的静态方法,它对父类方法只能起到隐藏的作用。调用的时候用谁的引用,则调用谁的版本。)
多态存在的三个比较条件:
1.要有继承
2.要有重写
3.父类的引用指向子类的对象
(3)多态的效果
1.对于指向子类对象的父类来说,在编译期间只能调用父类的方法,不能直接调用子类的方法。
2.对于父子类都有的非静态方法来说,最终调用子类中的重写版本。
3.对于父子类中都有的静态方法来说 ,最终调用父类中的版本,与指向的对象类型无关。
(4)案例
public class TestPersonStudent {
public static void main(String[] args) {
//使用父类的引用指向父类自己的对象
Person p = new Person();
p.show();
/**
* 运行结果:
* 小白 18
*/
//使用子类的引用指向子类自己的对象
System.out.println("--------------------");
Student s = new Student();
s.show();
/**
* 运行结果:
* 小白 18
* 学号是1
*/
//使用父类的引用指向子类的对象,形成多态
System.out.println("--------------------");
//发生由Student类型向Person类型的转换,小范围向大范围,自动类型转换
Person ps = new Student("小黑",19,2);
//解析:在编译期间调用的是Person.show(),在执行期间调用的是Student.show()
ps.show();
/**
* 运行结果:
* 小黑 19
* 学号是2
*/
//使用ps调用非静态方法进行测试
System.out.println("--------------------");
String str = ps.getName();
//ps是Person类型的引用,因此可以调用Person类的方法
System.out.println("获取到的名字是"+str);
/*
* int num = ps.getId(); (X)
* 子类可访问调用父类的信息,但父类无法访问调用子类
*/
/**
* 运行结果:
* 获取到的名字是小黑
*/
//使用ps调用静态方法进行测试
System.out.println("--------------------");
ps.test(); //警告
Person.test(); //静态成员推荐使用类名.的方式访问
//ps.test2(); (X)
Student.test(); //当Student类中没有test()时,会自动调用父类中的test()
Student.test2();
/**
* 运行结果:
* Person类的静态方法
* Person类的静态方法
* Person类的静态方法
* Student类的静态方法
*/
//如何实现子类方法的调用
System.out.println("--------------------");
//由Person类型向Student类型的转换,大-》小,强制类型转换
Student st = (Student) ps;
int num = st.getId();
System.out.println("ID是"+num);
/**
* 运行结果:
* ID是2
*/
}
}
二、引用类型之间的转换
(1)基本概念
引用类型之间的转换必须发生在父子类之间,分为自动类型转换(向上转型)和强制类型转换(向下转型)。
Ⅰ.向上转型
父类引用指向子类对象:
Animal dog = new Dog();
把一个子类对象转换为父类对象,这种转型一共发生在三个地方:
①产生对象时
Animal animal = new Dog();
②方法参数传递
public void fun(Animal animal){}
fun(new Dog());
③方法返回值
public Animal test(){
return new Dog();
}
注意:
当执行animal.eat();时,因为new的是子类Dog,所以是运行子类重写父类的方法以及父类派生的方法,无法调用子类独有的方法。若子类没有重写,则调用父类的方法。
父类中的静态方法无法被子类重写,所以向上转型之后只能调用父类原有的静态方法。
Ⅱ.向下转型
子类引用指向父类实例,必须进行强制类型转换,可以调用子类特有的方法。
Animal animal = new Bird();
Bird bird = (Bird) animal;
bird.fly();
这种转型有一定的风险性:
Person ps = new Student(“小黑”,19,2);
Teacher t = (Teacher)ps; (X)
当没有父子类关系发生强制类型转换则编译报错,当拥有父子类关系发生强制转换是编译通过;若目标类型并不是该引用真正指向的类型时,在运行阶段发生类型转换异常。
转型的前提:必须满足转型的条件
为了避免上述错误的发生,通常只要进行强制类型转换就需要进行判断,格式如下:
if (引用变量名 instanceof 数据类型) {}
instanceof 运算符可以进行判断,左侧对象是否满足右侧对象类型的特征。满足则返回true,否则返回false
if(animal instanceof Bird){}
总结
提示:这里对文章进行总结:
以上就是今天的学习内容,本文是继续Java面向对象的学习,学习了多态、向上转型、向下转型,这些内容刚开始会觉得难理解,多写就会熟悉。之后的学习内容将持续更新!!!