当前位置: 首页 > news >正文

黑马Java零基础视频教程精华部分_10_面向对象进阶(2)

系列文章目录


文章目录

  • 系列文章目录
  • 一、多态
    • 1、什么是多态?
    • 2、多态的表现形式
    • 3、多态的前提
    • 4、多态的好处
    • 5、多态调用成员的特点
    • 6、多态的优势和弊端
    • 7、引用数据类型的类型转换
  • 二、包
    • 1、什么是包?
    • 2、包名的规则
    • 3、使用其他类的规则
  • 三、final 最终的,不可变的
  • 四、权限修饰符
    • 1、权限修饰符分类
    • 2、权限修饰符的使用规则
  • 五、代码块
    • 1、局部代码块:提前结束变量的生命周期
    • 2、构造代码块:创建本类对象时优先于构造方法执行,可以把多个构造方法中重复的地方放在构造代码块中。
    • 3、静态代码块


一、多态

1、什么是多态?

同类型的对象,表现出不同的形态。

2、多态的表现形式

在这里插入图片描述

3、多态的前提

  1. 有继承/实现关系
  2. 有父类引用指向子类对象
  3. 有方法重写

4、多态的好处

使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利。
多态示例,如下图所示:学生,老师,管理员三各类都是Person的子类
在这里插入图片描述

5、多态调用成员的特点

变量调用:编译看左边,运行也看左边。
方法调用:编译看左边,运行看右边。
代码示例如下所示,注意看注释:

public class Test {public static void main(String[] args) {//创建对象(多态方式)//Fu f = new Zi();Animal a = new Dog();//调用成员变量:编译看左边,运行也看左边//编译看左边:javac编译代码的时候,会看左边的父类中有没有这个变量,如果有,编译成功,如果没有编译失败。//运行也看左边:java运行代码的时候,实际获取的就是左边父类中成员变量的值System.out.println(a.name);//动物//调用成员方法:编译看左边,运行看右边//编译看左边:javac编译代码的时候,会看左边的父类中有没有这个方法,如果有,编译成功,如果没有编译失败。//运行看右边:java运行代码的时候,实际上运行的是子类中的方法。a.show();///输出“Dog --- show方法”//理解://Animal a = new Dog();//现在用a去调用变量和方法的呀?是的//而a是Animal类型的,所以默认都会从Animal这个类中去找//成员变量:在子类的对象中,会把父类的成员变量也继承下来。父:name  子:name//成员方法:如果子类对方法进行了重写,那么在虚方法表中是会把父类的方法进行覆盖的。}
}class Animal{String name = "动物";public void show(){System.out.println("Animal --- show方法");}
}class Dog extends Animal{String name = "狗";@Overridepublic void show() {System.out.println("Dog --- show方法");}}class Cat extends Animal{String name = "猫";@Overridepublic void show() {System.out.println("Cat --- show方法");}
}

内存图示意如下:为什么是左边或者右边是固定的,此图只是帮助理解记忆。在一个类存在父类时,在方法区都是先加载父类的字节码文件,再加载子类的字节码文件(.class文件)。所谓看左边就是在定义时(Animal a = new Dog())看a的左边是哪个类,然后找该类中是否存在或者使用其成员变量或者方法,编译时就是看有没有其成员变量或者方法,而运行时就是使用其成员变量或者方法。
在这里插入图片描述

6、多态的优势和弊端

优势:方法中,使用父类型作为参数,可以接收所有子类对象
弊端:不能使用子类的特有功能,此时需要使用强制类型转换,代码如下所示,注意理解注释:

public class Test {public static void main(String[] args) {//创建对象Animal a = new Dog();//编译看左边,运行看右边a.eat();//多态的弊端//不能调用子类的特有功能//报错的原因?//当调用成员方法的时候,编译看左边,运行看右边//那么在编译的时候会先检查左边的父类中有没有这个方法,如果没有直接报错。//a.lookHome();//解决方案://变回子类类型就可以了//细节:转换的时候不能瞎转,如果转成其他类的类型,就会报错//Cat c = (Cat) a;//c.catchMouse();/*if(a instanceof Dog){Dog d = (Dog) a;d.lookHome();}else if(a instanceof Cat){Cat c = (Cat) a;c.catchMouse();}else{System.out.println("没有这个类型,无法转换");}*///新特性//先判断a是否为Dog类型,如果是,则强转成Dog类型,转换之后变量名为d//如果不是,则不强转,结果直接是falseif(a instanceof Dog d){d.lookHome();}else if(a instanceof Cat c){c.catchMouse();}else{System.out.println("没有这个类型,无法转换");}}
}class Animal{public void eat(){System.out.println("动物在吃东西");}
}class Dog extends Animal{@Overridepublic void eat() {System.out.println("狗吃骨头");}public void lookHome(){System.out.println("狗看家");}
}class Cat extends Animal{@Overridepublic void eat() {System.out.println("猫吃小鱼干");}public void catchMouse(){System.out.println("猫抓老鼠");}
}

7、引用数据类型的类型转换

对于引用数据类型,在父类和子类的继承层次关系中,沿着子类向父类转换是向上转型,是自动转换的;沿着父类向子类转型是向下转型,必须使用强制类型转换。

二、包

1、什么是包?

包就是文件夹。用来管理各种不同功能的Iava类,方便后期代码维护。

2、包名的规则

公司域名反写+包的作用需要全部英文小写,见名知意。com.itheima.domain就是放一些实体类。比如com.itheima.domain.Student这才是类真正的名。
在这里插入图片描述
上图可以用导包简化如下所示:
在这里插入图片描述

3、使用其他类的规则

  1. 使用同一个包中的类时,不需要导包。
  2. 使用包中的类时,不需要导包。
  3. java.lang 其他情况都需要导包
  4. 如果同时使用两个包中的同名类,需要用全类名

三、final 最终的,不可变的

1.final修饰方法:最终方法,不能被重写
2.final修饰类:最终类,不能被继承
3.final修饰变量:是常量,不能被修改。基本数据类型:变量的值不能修改引用数据类型:地址值不能修改,内部的属性值可以修改。
final使用示例如下:增加代码可阅读性。
在这里插入图片描述

四、权限修饰符

权限修饰符:是用来控制一个成员能够被访问的范围的。
可以修饰成员变量,方法,构造方法,内部类,

1、权限修饰符分类

如下图所示,打对号表示可以使用。
在这里插入图片描述
其中同一个包中的其他类和不同包下的无关类的意思是要创建一个对象,然后用它来调用权限修饰符修饰的变量或者方法。

2、权限修饰符的使用规则

实际开发中,一般只用private和public。成员变量私有方法公开。特例:如果方法中的代码是抽取其他方法中共性代码,这个方法一般也私有。

五、代码块

1、局部代码块:提前结束变量的生命周期

在这里插入图片描述

2、构造代码块:创建本类对象时优先于构造方法执行,可以把多个构造方法中重复的地方放在构造代码块中。

在这里插入图片描述
缺点:不够灵活,我有时候不想运行构造代码块中的代码,但无法让构造代码块不执行。比如有三个构造函数,其中只有两个我想执行构造代码块中的内容,这种情况我们不能在设置构造代码块,因为那样三个构造函数一定都会使得构造代码块被执行,我们需要如下图所示,我们把重复的语句不再放在构造代码块中,而是放在一个构造函数中,当调用其他构造函数创建对象时,我们通过构造函数调用其他包含重复代码的构造函数即可。
在这里插入图片描述

3、静态代码块

格式:static{}
特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发只执行一次,也就是你创建多余一个对象只会执行一次(也就是内存中只会有一份,避免了被多次调用时候,存多份相同数据在内存中,占用内存的漏洞)。如下图所示。
作用:

  1. 初始化静态变量:‌静态代码块可以用于初始化类中的静态变量。‌在类加载时,‌静态代码块执行,‌可以对静态变量进行赋初值操作。‌
  2. 执行一次性初始化操作:‌静态代码块在类加载时只执行一次,‌因此非常适合执行一次性的初始化操作,‌如读取配置文件、‌建立数据库连接等。‌
  3. 预加载资源:‌静态代码块可以在类加载时预加载一些资源,‌如常用的数据,‌以提高程序的性能。‌

在这里插入图片描述

相关文章:

  • 位运算(更新中)
  • 本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——2Yolo使用之ONNX模型准备
  • PE安装win11原版系统“无法创建新的分区,也找不到现有的分区”和“windows无法对计算机进行启动到下一个安装阶段”的解决办法
  • 【参会邀请】第四届区块链技术与信息安全国际会议(ICBCTIS 2024)诚邀相聚江城!
  • 代码随想录第五十七天
  • Vue 常用组件间通信方式
  • 代码随想录算法训练营第 32 天 | LeetCode509斐波那契数列 LeetCode70爬楼梯 LeetCode749使用最小花费爬楼梯
  • 华为路由常见 LSA 类型的产生及作用域和字段详细解读
  • 杰理-1拖8 错误状态
  • 程序员找工作之操作系统面试题总结分析
  • 【Unity实战】给Unity的类添加新功能
  • Android笔试面试题AI答之线程Handler、Thread(3)
  • 基于 Kafka 的经验:AutoMQ 和 MinIO 如何解决成本和弹性挑战
  • 使用redis缓存文章浏览量
  • PHP中如何处理字符串
  • 时间复杂度分析经典问题——最大子序列和
  • [Vue CLI 3] 配置解析之 css.extract
  • Android系统模拟器绘制实现概述
  • Cumulo 的 ClojureScript 模块已经成型
  • C学习-枚举(九)
  • docker容器内的网络抓包
  • ES6语法详解(一)
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • HTTP那些事
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • JavaScript设计模式系列一:工厂模式
  • Markdown 语法简单说明
  • redis学习笔记(三):列表、集合、有序集合
  • springMvc学习笔记(2)
  • Travix是如何部署应用程序到Kubernetes上的
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 第十八天-企业应用架构模式-基本模式
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 排序算法学习笔记
  • 深度学习入门:10门免费线上课程推荐
  • 手写双向链表LinkedList的几个常用功能
  • 微信开源mars源码分析1—上层samples分析
  • 无服务器化是企业 IT 架构的未来吗?
  • 与 ConTeXt MkIV 官方文档的接驳
  • 原生Ajax
  • Nginx实现动静分离
  • # Apache SeaTunnel 究竟是什么?
  • # Java NIO(一)FileChannel
  • # 计算机视觉入门
  • #### golang中【堆】的使用及底层 ####
  • #java学习笔记(面向对象)----(未完结)
  • #QT(智能家居界面-界面切换)
  • (09)Hive——CTE 公共表达式
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (TOJ2804)Even? Odd?
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (微服务实战)预付卡平台支付交易系统卡充值业务流程设计