#Java-面向对象进阶-多态

1.多态

多态是面向对象三大特征之一,表示同类型的对象表现不同的形态
表现形式:

父类类型 对象名称 = 子类对象;

多态的前提:

  • 有继承关系

  • 有父类引用子类

      Fu  f = new Zi();
    
  • 有方法重写

使用场景举例:

当需要写一个注册的方法,但是这个方法要能实现不同对象的注册
例如:老师、学生、管理员
就可以使用多态实现:使用父类person,来引用子类

在这里插入图片描述

前面我们说需要:父类 对象名称 = 子类对象 父类引用子类
这里实际上是在方法传参的时候引用了preson p,传入子类对象


2.多态调用成员变量的特点

  • 成员变量:编译看左边,运行看左边
  • 成员方法:编译看左边,运行看右边
//父类和子类
class person{
	String name = "fu";
	public void show(){}
}
class zi{
	String name = "zi";
	@Override
	public void show(){}
}
//调用:
person p = new zi();
p.name;
p.show();

a. 成员变量

person p = new zi()
编译:编译看左边: 当javac在编译的时候会看父类中有没有这个成员变量,如果有就编译成功,没有就报错
运行:运行看左边:当java在运行代码的时候,实际获取的就是左边父类中成员变量的值

所以上述代码:p.name的值是fu

  • 实际也好理解:Javac在编译时会根据引用的类型来决定访问哪个变量。
  • 子类中可以不写成员变量

b.成员方法

person p = new zi()
编译:编译看左边: javac在编译的时候会看父类中有没有这个方法,如果有就编译成功,没有就报错
运行:运行看右边:实际上运行的是在子类中重写的方法

所以上述代码:p.show(),调用的时子类中的方法

  • 理解:从虚方法表的角度来看:子类的方法重写覆盖了父类虚方法表中的这个方法。
  • 当子类中没有方法重写时,直接调用父类中的方法

c. 从内存的角度理解

  1. 加载测试类的字节码文件进入方法区
  2. 加载main方法进栈
  3. 加载子类和父类的字节码文件进方法区

    实际上是从父类开始加载字节码文件的,例如:person p = new zi()先加载object.class之后是:person.class,然后是zi.class

  4. 创建对象:变量(对象变量/对象引用)在栈中,存储地址;对象的数据存储在堆内存中,把地址拿给变量

    在对象中数据分为两块:一块是父类中的数据,另一块是子类中的数据

  5. 在访问同一个成员变量时:优先访问对象中父类的数据
  6. 在访问成员方法的时候,访问的时子类中的成员方法

图示:来自黑马程序员
在这里插入图片描述


3.多态的优势和弊端

a.优势

  • 代码的可移植性高:例如:

      person p = new student();
      p.work();//调用的是子类中的方法
    

    可以修改其中的子类,同时下面的方法调用也会改变

  • 定义方法时,使用父类作为参数,可以接收所有的子类对象。


b.弊端

  • 代码不能访问子类特有的方法
Fu f= new Zi();

我们说过子类在调用方法时:编译看父类,运行看子类。
当父类中没有这个方法时,子类不能调用


当然我们有对策:
可以使用强制类型转换来访问:
例如:

Zi z = (Zi) f;
f.show();

在实际编写代码时:完整:

if (a instanceof Zi1) {
	Zi1 b = (Zi1) a;
	b.show();
}
else if(a instanceof Zi2) {
	Zi2 c = (Zi2) a;
	c.show();
} 
  • instanceof关键字:左边是对象变量,右边是类名,判断变量类型是否和类一致,返回boolean类型
  • 在JDK14之后为代码做了优化
if (a instanceof Zi1 b) {
	b.show();
}
else if(a instanceof Zi2 c) {
	c.show();
} 
//把判断和强制转换化作了一行
//如果是:进行转换并进入if语句,不是则返回false

补充:自动类型转换:类型小的自动转换为类型大的
parent p = new son()父类:parent,子类:son


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值