本文参照教科书《Java语言程序设计与数据结构(第11版)》以及网上资料进行编写。
参考网址:https://www.runoob.com/java/java-polymorphism.htmlhttps://www.bilibili.com/video/BV134411Q7iD?p=42
JAVA——多态
本文关键词:JAVA、多态
文章目录
- JAVA——多态
- 一、多态的简介
- 1.JAVA的多态
- 2.多态三要素
- 3.多态的成员访问
- 4.多态的优点
- 二、JAVA多态实例
- 三、多态的实现方式
- 1.重写或重载
- 2.接口
- 3.抽象类和抽象方法
- 四、多态的转型
- 1.向上转型
- 2.向下转型
一、多态的简介
1.JAVA的多态
多态(polymorphism)顾名思义:多态就是多种形式、多种状态,在面向对象语言中,接口的多种不同的实现方式即为多态,它是面向对象的程序设计语言最核心的特征。多态是多种状态的现象,不是代表具体的一句代码,例如:金鱼可以说是一种海洋动物,也可以说是一条鱼等等。下面让我们一起走进Java多态的世界。
- 编译时多态
- 编译期间决定目标方法
- 通过overloading重载实现
- 方法名相同,参数不同
eg:编译时,根据参数不同执行不同的程序
- 运行时多态
- 运行期间决定目标方法
- 同名同参
- overriding和继承实现
- JVM决定目标方法
2.多态三要素
- 继承或者实现的关系
//创建Dog类,继承Animal类
public class Dog extends Animal{
//代码
}
- 方法重写
//方法重写,具体到子类
@Override
public void run() {
System.out.println("Dog runs fast!");
}
- 父类引用指向子类对象
//父类引用指向子类对象
Animal dog = new Dog(); //体现多态
3.多态的成员访问
- 成员变量:编译时看父类、运行时看父类
- 直接通过对象名称访问成员变量:等号左边优先用
- 间接通过成员方法访问
- 成员方法:编译时看父类、运行时看子类
4.多态的优点
优点:
- 可以作为方法提高代码的拓展性和维护性
- 降低类之间的耦合性,使代码的关联变少
- 接口性
- 灵活性
- 可扩充性
- 简化性
弊端:
- 无法访问子类特有的成员(可以被解决)
二、JAVA多态实例
代码中来体现多态性:父类引用指向子类对象。
- 格式:
- 父类名称 对象名 =new 子类名称();
- 接口名称 对象名 =new 实现类名称();
实例:
首先创建一个polymorphism包,里面建立一个Animal类,定义方法run和变量size。
package polymorphism;
public class Animal {
int size= 10;
//定义方法run
public void run() {
System.out.println("run run run!");
}
}
接着我们来创建一个Dog子类,继承Animal类
package polymorphism;
//创建Dog类,继承Animal类
public class Dog extends Animal{
//成员变量访问
int size =5;
//方法重写,具体到子类
@Override
public void run() {
System.out.println("Dog runs fast!");
}
}
在包内创建一个text类,来进行JAVA实例演示
- 成员访问:
package polymorphism;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
//父类引用指向子类对象
Animal dog = new Dog(); //体现多态
//成员变量访问:编译看父类,运行看父类
System.out.println(dog.size);
//成员方法访问:编译看父类(父类有则正常编译),运行看子类
dog.run();
}
}
运行结果如下
10
Dog runs fast!
可以看出,进行成员变量访问时,编译和运行都要取决于父类,而进行成员方法访问时,运行要取决于子类,但是编译还是要看父类中有无此方法定义。
- JAVA多态优点体现
- 降低类之间的耦合性,提高代码扩展性
我们继续创建一个新的子类Cat,同样进行方法重写。
package polymorphism;
public class Cat extends Animal{
@Override
public void run() {
System.out.println("Cat runs slowly!");
}
}
当我们想访问子类的成员方法时,创建一个method方法来继续进行。
方法一:
package polymorphism;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Dog dog=new Dog();
method(dog);
Cat cat=new Cat();
method(cat);
}
public static void method(Dog dog) {
dog.run();
}
public static void method(Cat cat) {
cat.run();
}
}
运行结果
Dog runs fast!
Cat runs slowly!
运用多态时:
package polymorphism;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Dog dog=new Dog();
method(dog);
Cat cat=new Cat();
method(cat);
}
//运用多态——提高代码的扩展性
public static void method(Animal animal) {
animal.run();
}
}
运行结果
Dog runs fast!
Cat runs slowly!
我们可以看到两个方法实际上是一样的效果,当子类较多时,多态优势便更加显著的体现出来。
三、多态的实现方式
1.重写或重载
- 重载意味着使用同样的名字但是不同的签名来定义多个方法。重写意味着在子类中提供一个对方法的新的实现。
- 重写
//方法重写
public class Test1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
A a=new A();
a.p(10);
a.p(10.0);
}
}
class B{
public void p(double i) {
System.out.println(i*2);
}
}
class A extends B{
//This method overrides the method in B
public void p(double i) {
System.out.println(i);
}
}
输出结果
10.0
10.0
- 重载
//方法重载
public class Test2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
C c=new C();
c.p(10);
c.p(10.0);
}
}
class D{
public void p(double i) {
System.out.println(i*2);
}
}
class C extends D{
//This method overloads the method in B
public void p(int i) {
System.out.println(i);
}
}
输出结果
10
20.0
- 注意:
- 方法重写发生在具有继承关系的不同类中
- 方法重载可以发生在同一个类中,也可以发生在具有继承关系的不同类中。
- 参数列表与被重写方法的参数列表必须完全相同
- 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类
- 访问权限不能比父类中被重写的方法的访问权限更低。比如父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。
.> - 父类的成员方法只能被它的子类重写。- 声明为final的方法不能被重写
- 声明为static的方法不能被重写,但是能够被再次声明。
- 子类和父类在同一个包中,那么子类可以重写父类的所有方法,除了声明为private和final的方法
- 子类和父类不在同一个包中,那么子类只能够重写父类的声明为public和protected和非final方法。
- 重写方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
- 构造方法不能重写
- 如果不能继承一个类,则不能重写该类的方法
2.接口
生活中的接口最具代表性的是插座
Java中的接口类似于生活中的接口,即一些方法特征的集合。
3.抽象类和抽象方法
继承抽象方法的子类必须重写方法。否则,该子类也必须声明为抽象类。
四、多态的转型
1.向上转型
- 格式:父类名称 对象名 = new 子类名称();
- 含义: 右侧创建一个子类对象,把它当做父类来看待使用
- 注意:向上转型一定是安全的,从小范围转向了大范围,例如:从一条鱼向上转换为一个海洋动物。
- 当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作,通常使用向上转型。
- 类似于:自动类型转换:double x=2;
//向上转型
Animal animal=new Dog();
2.向下转型
- 格式:子类名称 对象名 = (子类名称)父类对象;
- 含义:将父类对象还原成为本来的子类对象
- 注意事项:
- 必须保证对象创建时就是小范围对象,被认为是大范围对象,才能向下转型成为原本的小范围对象;例如,创建一个海洋动物是一条金鱼,那么这条金鱼就可以还原为金鱼。
- 如果对象创建时不是本来的小范围对象,要强制向下转型为原来的小范围对象,则会报错ClassCastException。
- 当要使用子类特有功能时,就需要使用向下转型。
- 类似于:强制类型转换:int a=(int)10.5;(不可以转换)
//向下转型
Dog dog= (Dog) animal;
本文就到此结束啦,谢谢观看~