首页 > 编程语言 >#Java-面向对象进阶-多态

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

时间:2024-11-16 14:45:24浏览次数:3  
标签:Java 进阶 show 子类 多态 编译 new 父类 方法

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


标签:Java,进阶,show,子类,多态,编译,new,父类,方法
From: https://blog.csdn.net/2302_80203877/article/details/143814161

相关文章

  • Java序列化与反序列化深度解析
    一、引言在Java开发中,序列化与反序列化是非常重要的概念和技术手段。它允许我们将对象转换为字节流以便于存储或传输,然后在需要的时候再将字节流还原为对象。这一机制在很多场景中都有着广泛的应用,例如数据持久化、分布式系统中的远程方法调用(RMI)、缓存等。本文将深入探讨......
  • 7.Java 注解和元注解(三种注解、四种元注解)
    一、注解概述注解也被称为元数据,用于修饰包、类、方法等数据信息和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息在JavaSE中,注解使用的目的比较简单,例如标记过时的功能,忽略警告等JavaEE中注解会充当更加重要的角色二、三种注......
  • JavaScript判断用户设备类型:PC端与移动端的区分方法
    在JavaScript中,可以通过检查用户代理字符串(UserAgentString)来判断用户设备类型,即访问网站的是PC端还是移动端设备。用户代理字符串是浏览器在发送HTTP请求时附带的一段信息,它包含了浏览器类型、版本、操作系统以及设备类型等信息。以下是一个简单的示例代码,用于判断用户......
  • 一文详解Java反射技术
    Java反射什么是Java反射以及引出反射的背景?Class类如何获取一个class的Class实例Class类的使用获取属性获取调用方法获取注解信息获取构造方法反射的应用什么是Java反射以及引出反射的背景?Java程序中的对象有两种类型,编译时类型和运行时类型,而很多时候编译......
  • Java反序列化-Commons Collections3利用链分析详解
    介绍CC3与CC1和CC6的主要区别在于,CC1和CC6依赖反射机制来执行Runtime.getRuntime().exec()等危险命令,而如果服务器将这些方法列入黑名单,这两种方式就会失效。相比之下,CC3通过类加载器动态加载恶意类来执行危险函数,绕过黑名单限制,从而达到命令执行的目的。公众号:T......
  • java笔试题
    请指出下面程序的运行结果(62)publicclassTest{publicstaticvoidmain(String[]args){System.out.println(test());}publicstaticinttest(){try{return2;}catch(Exceptione){return4;......
  • 前端必知必会-JavaScript if、else 和 else if
    文章目录JavaScriptif、else和elseif条件语句if语句else语句elseif语句总结JavaScriptif、else和elseif条件语句用于根据不同的条件执行不同的操作。条件语句编写代码时,您经常希望针对不同的决策执行不同的操作。您可以在代码中使用条件语句来执行......
  • 前端必知必会-JavaScript Switch 语句
    文章目录JavaScriptSwitch语句JavaScriptSwitch语句break关键字default关键字常见代码块switch详细信息严格比较总结JavaScriptSwitch语句switch语句用于根据不同的条件执行不同的操作。JavaScriptSwitch语句使用switch语句从多个代码块中选择一个......
  • java根据时区转换获取时间的方法
    方法一:publicstaticvoidmain(String[]args){//假设这是从MySQL获取的UTC时间字符串StringutcTimeStr="2024-09-30T16:00:00Z";try{//解析UTC时间字符串DateTimeparsedDateTime=DateUtil.parse(utcTimeStr......
  • Java Web 过滤器和拦截器.
    概念过滤器即Servlet过滤器,参见Servlet过滤器入门示例。拦截器(Interceptor)通常是由特定的框架提供的,不是JavaEE标准的一部分。Spring提供了多种类型的拦截器,如方法拦截器(MethodInterceptor)和控制器拦截器(HandlerInterceptor)。方法拦截器可以用于AOP(面向切面编程),而控......