第八章面向对象编程(中级)

news2024/11/19 6:43:39

8.1访问修饰符
8.1.1基本介绍
java提供四种访问控制修饰符号,用于控制方法和属性(成员变量)的访问权限(范围):

  1. 公开级别:用 public 修饰,对外公开
  2. 受保护级别:用 protected 修饰,对子类和同一个包中的类公开
  3. 默认级别:没有修饰符号,向同一个包的类公开. 4) 私有级别:用 private 修饰,只有类本身可以访问,不对外公开.

4种访问修饰符的访问范围
在这里插入图片描述
使用的注意事项
在这里插入图片描述
8.2面向对象编程三大特征
8.2.1基本介绍
面向对象编程有三大 特征:封装,继承,和多态

封装:encapsulation就是把抽象出的数据【属性】和对数据的操作【方法】封装在一起,数据被保护在内部,程序的其他部分只有通过被授予的操作【方法】,才能对数据进行操作。

8.2.2封装的理解和好处
在这里插入图片描述
8.2.3封装的实现步骤(三步)
在这里插入图片描述
8.3快速入门
在这里插入图片描述
代码略
可以将构造器和setXxx结合

//有三个属性的构造器
public Person(String name, int age, double salary) {
	// this.name = name;
	// this.age = age;
	// this.salary = salary;
	//我们可以将 set 方法写在构造器中,这样仍然可以验证
	setName(name);
	setAge(age);
	setSalary(salary);
}

setXxx方法中可以设置一些约束
例如:

//姓名(长度为 2 位 3 位或 4 位)
public void setName(String name) {
	if (name.length() >= 2 && name.length() <= 4) {
	this.name = name;
	} else {
	System.out.println("姓名要求(长度为 2 位 3 位或 4 位),默认值 无名");
	this.name = "无名";
	}
}

//余额(必须>20)
public void setBalance(double balance) {
	if (balance > 20) {
	this.balance = balance;
	} else {
	System.out.println("余额(必须>20) 默认为 0");
	}
}

//密码(必须是六位)
public void setPwd(String pwd) {
	if (pwd.length() == 6) {
	this.pwd = pwd;
	} else {
	System.out.println("密码(必须是六位)默认密码为 000000");
	this.pwd = "000000";
	}
}

8.4面向对象编程-继承
8.4.1为什么需要继承?
在这里插入图片描述
8.4.2继承基本介绍和示意图
在这里插入图片描述
8.4.3继承的基本语法
在这里插入图片描述
8.4.4继承给编程带来的便利

  1. 代码的复用性提高了
  2. 代码的扩展性和维护性提高了

8.4.5继承的深入讨论/细节问题
在这里插入图片描述
在这里插入图片描述
输入 ctrl + H 可以看到类的继承关系

8.5继承的本质分析
在这里插入图片描述

package com.hspedu.extend_;
/**
* 讲解继承的本质
*/
public class ExtendsTheory {
	public static void main(String[] args) {
		Son son = new Son();//内存的布局
		//?-> 这时请大家注意,要按照查找关系来返回信息
		//(1) 首先看子类是否有该属性
		//(2) 如果子类有这个属性,并且可以访问,则返回信息
		//(3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)
		//(4) 如果父类没有就按照(3)的规则,继续找上级父类,直到 Object... System.out.println(son.name);//返回就是大头儿子
		//System.out.println(son.age);//返回的就是 39
		//System.out.println(son.getAge());//返回的就是 39
		System.out.println(son.hobby);//返回的就是旅游
	}
}
class GrandPa { //爷类
	String name = "大头爷爷";
	String hobby = "旅游";
}
class Father extends GrandPa {//父类
	String name = "大头爸爸";
	private int age = 39;
	public int getAge() {
		return age;
	}
}
class Son extends Father { //子类
	String name = "大头儿子";
}

子类创建的内存布局
在这里插入图片描述
课堂练习:
在这里插入图片描述
8.6super关键字
8.6.1基本介绍
super代表父类的引用,用于访问父类的属性、方法、构造器
8.6.2基本语法
在这里插入图片描述
super 的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用 super 去访问爷爷类的成员;
如果多个基类(上级类)中都有同名的成员,使用 super 访问遵循就近原则。A->B->C

super().xx和this.xx:
找xx 和 this.xx()),顺序是:
(1)先找本类,如果有,则调用
(2)如果没有,则找父类(如果有,并可以调用,则调用)
(3)如果父类没有,则继续找父类的父类,整个规则,就是一样的,直到 Object 类
// 提示:如果查找方法的过程中,找到了,但是不能访问, 则报错, cannot access
// 如果查找方法的过程中,没有找到,则提示方法不存在
xx 和 thisxx 查找的规则是
(1) 先找本类,如果有,则调用
(2) 如果没有,则找父类(如果有,并可以调用,则调用)
(3) 如果父类没有,则继续找父类的父类,整个规则,就是一样的,直到 Object 类

super给编程带来的便利/细节
在这里插入图片描述
super和this的比较
在这里插入图片描述
8.7方法重写/覆盖(override)
8.7.1基本介绍
简单的说:方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么就说子类的这个方法覆盖了父类的方法。

8.7.2注意事项和使用细节
方法重写也叫方法覆盖,需要 满足以下条件:
在这里插入图片描述
方法重载和重写的比较:
在这里插入图片描述
8.8面向对象编程-多态
8.8.1多[多种]态[状态]基本介绍
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。
1)方法的多态
重写和重载就体现多态

package com.hspedu.poly_;
public class PloyMethod {
	public static void main(String[] args) {
		//方法重载体现多态
		A a = new A();
		//这里我们传入不同的参数,就会调用不同 sum 方法,就体现多态
		System.out.println(a.sum(10, 20));
		System.out.println(a.sum(10, 20, 30));
		//方法重写体现多态
		B b = new B();
		a.say();
		b.say();
		}
}
class B { //父类
	public void say() {
		System.out.println("B say() 方法被调用...");
	}
}
class A extends B {//子类
	public int sum(int n1, int n2){//和下面 sum 构成重载
		return n1 + n2;
		}
		public int sum(int n1, int n2, int n3){
		return n1 + n2 + n3;
		}
		public void say() {
		System.out.println("A say() 方法被调用...");
	}
}

2)对象的多态
重点注意:
1)一个对象的编译类型和运行类型可以不一致;
2)编译类型在定义对象时,就可以确定了,不能改变;
3)运行类型是可以改变的;
4)编译类型看定义时=号的左边,运行类型看=号的右边。
例子:
在这里插入图片描述

public class PolyObject {
	public static void main(String[] args) {
		//体验对象多态特点
		//animal 编译类型就是 Animal , 运行类型 Dog
		Animal animal = new Dog();
		//因为运行时 , 执行到改行时,animal 运行类型是 Dog,所以 cry 就是 Dog 的 cry
		animal.cry(); //小狗汪汪叫
		//animal 编译类型 Animal,运行类型就是 Cat
		animal = new Cat();
		animal.cry(); //小猫喵喵叫
	}
}

8.8.2多态注意事项和细节讨论
在这里插入图片描述
√属性没有重写之说!属性的值看编译类型
√instanceOf 比较操作符,用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型

public static void main(String[] args) {
	//向上转型: 父类的引用指向了子类的对象
	//语法:父类类型引用名 = new 子类类型();
	Animal animal = new Cat();
	Object obj = new Cat();//可以吗? 可以 Object 也是 Cat 的父类
	//多态的向下转型
	//(1)语法:子类类型 引用名 =(子类类型)父类引用;
	//问一个问题? cat 的编译类型 Cat,运行类型是 Cat
	Cat cat = (Cat) animal;
	cat.catchMouse();//猫抓老鼠
	//(2)要求父类的引用必须指向的是当前目标类型的对象
	}
}

课堂练习:
在这里插入图片描述
8.8.2java的动态绑定机制
1)当调用对象方法 的时候,该方法会和该对象的内存地址/运行类型绑定
2)当调用对象属性时,没有动态绑定机制,哪里申明,哪里使用

8.8.3多态的应用
1)多态数组
数组的定义类型为父类类型,里面保存的实际元素类型为子类类型
应用实例:现有一个继承结构如下:要求创建 1 个 Person 对象、2 个 Student 对象和 2 个Teacher 对象, 统一放在数组中,并调用每个对象的say 方法.
应用实例升级:如何调用子类特有的方法,比如Teacher 有一个 teach , Student 有一个 study怎么调用?

public class PloyArray {
	public static void main(String[] args) {
		//应用实例:现有一个继承结构如下:要求创建 1 个 Person 对象、
		// 2 个 Student 对象和 2 个 Teacher 对象, 统一放在数组中,并调用每个对象 say 方法
		Person[] persons = new Person[5];
		persons[0] = new Person("jack", 20);
		persons[1] = new Student("mary", 18, 100);
		persons[2] = new Student("smith", 19, 30.1);
		persons[3] = new Teacher("scott", 30, 20000);
		persons[4] = new Teacher("king", 50, 25000);
		//循环遍历多态数组,调用 say
		for (int i = 0; i < persons.length; i++) {
			//老师提示: person[i] 编译类型是 Person ,运行类型是是根据实际情况有 JVM 来判断
			System.out.println(persons[i].say());//动态绑定机制
			//这里大家聪明. 使用 类型判断 + 向下转型. if(persons[i] instanceof Student) {//判断 person[i] 的运行类型是不是 Student
			Student student = (Student)persons[i];//向下转型
			student.study();
			//小伙伴也可以使用一条语句 ((Student)persons[i]).study();
			} else if(persons[i] instanceof Teacher) {
				Teacher teacher = (Teacher)persons[i];
				teacher.teach();
			} else if(persons[i] instanceof Person){
			//System.out.println("你的类型有误, 请自己检查...");
			} else {
				System.out.println("你的类型有误, 请自己检查...");
			}
		}
	}
}

2)多态数组
在这里插入图片描述
8.9Object类详解
8.9.1equals方法
在这里插入图片描述
8.9.2如何重写equals方法

//重写 Object 的 equals 方法
public boolean equals(Object obj) {
	//判断如果比较的两个对象是同一个对象,则直接返回 true
	if(this == obj) {
	return true;
	}
	//类型判断
	if(obj instanceof Person) {//是 Person,我们才比较
	//进行 向下转型, 因为我需要得到 obj 的 各个属性
	Person p = (Person)obj;
	return this.name.equals(p.name) && this.age == p.age && this.gender == p.gender;
	}
	//如果不是 Person ,则直接返回 false
	return false;
}

8.9.3hashCode方法
在这里插入图片描述
在这里插入图片描述
8.9.4toString方法

  1. 基本介绍
    默认返回:全类名+@+哈希值的十六进制,【查看 Object 的 toString 方法】
    子类往往重写 toString 方法,用于返回对象的属性信息
  2. 重写 toString 方法,打印对象或拼接对象时,都会自动调用该对象的 toString 形式.
  3. 当直接输出一个对象时,toString 方法会被默认的调用
    重写 toString 方法, 输出对象的属性使用快捷键即可 alt+insert -> toString

8.9.5finalize方法

  1. 当对象被回收时,系统自动调用该对象的 finalize 方法。子类可以重写该方法
  2. 什么时候被回收:当某个对象没有任何引用时,则 jvm 就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用 finalize 方法。
  3. 垃圾回收机制的调用,是由系统来决定(即有自己的 GC 算法), 也可以通过 System.gc() 主动触发垃圾回收机制

8.10断点调试
在断点调试过程中,是运行状态,是以对象的运行类型来执行的
快捷键:
F7(跳入) F8(跳过) shift+F8(跳出) F9(resume,执行到下一个断点)
F7:跳入方法内
F8: 逐行执行代码. shift+F8: 跳出方法

零钱通项目
重点:代码思想
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
化繁为简.

  1. 先完成显示菜单,并可以选择
  2. 完成零钱通明细.
  3. 完成收益入账
  4. 消费
  5. 退出
package myself.smallchange.oop;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class Mainmenuoop {
    //相关变量
    boolean loop = true;//是否循环显示
    Scanner scanner = new Scanner(System.in);
    String key = "";

    double money = 0;
    double balance = 0;//余额

    String detail = "-----------零钱通菜单-----------";
    Date date = null;
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");

    String note = "";

    String hint = "";

    //查看零钱通明细
    public void showDetail(){
        System.out.println(detail);
    }

    //收益入账
    public void earn(){
        System.out.print("收益入账金额:");
        money = scanner.nextDouble();
        if(money <= 0){
            System.out.println("收益入账金额输入错误!");
            return;//退出方法不再执行后面的代码
        }
        balance += money;
        date = new Date();//获取当前日期
        //拼接收益入账信息到detail
        detail += String.format("\n收益入账\t+" + money + "\t"
                + sdf.format(date) + "\t" + "余额:" + balance );
    }

    //消费
    public void spend(){
        System.out.print("消费备注:");
        note = scanner.next();
        System.out.print("消费金额:");
        money = scanner.nextDouble();
        //如果消费金额小于等于0,或者余额不够就提示消费金额输入错误
        if(money <= 0 || balance < money){
            System.out.println("消费金额输入错误!");
            return;
        }
        balance -= money;
        date = new Date();//获取当前日期
        //拼接消费入账信息到detail
        detail += String.format("\n" + note + "\t\t-" + money + "\t"
                + sdf.format(date) + "\t" + "余额:" + balance );
    }

    //退出
    public void exit(){
        //定义一个choice,接收用户的输入
        //(1)使用while+break来处理接收到的输入是y或者n
        //(2)退出while后,再判断choice是y还是n,就可以决定是否退出
        while (true){
            //用户必须输入y/n,否则就一直循环
            System.out.println("你确定要退出嘛(y/n)?");
            hint = scanner.next();
            if ("y".equals(hint) || "n".equals(hint)){
                break;
            }
        }
        if (hint.equals("y")){
            loop = false;
            System.out.println("您已经退出零钱通。");
        }
    }

    //主菜单
    public void mainMenu(){
        do{
            System.out.println("-----------零钱通菜单oop-----------");
            System.out.println("\t\t\t1 零钱通明细");
            System.out.println("\t\t\t2 收益入账");
            System.out.println("\t\t\t3 消费");
            System.out.println("\t\t\t4 退出");
            System.out.print("请选择(1-4):");
            key = scanner.next();

            switch (key){
                case "1" :
                    showDetail();
                    break;
                case "2" :
                    earn();
                    break;
                case "3" :
                    spend();
                    break;
                case "4" :
                    exit();
                    break;
                default:
                    System.out.println("输入有误,请重新选择!");
                    break;
            }
        }while (loop);

    }

}



package myself.smallchange.oop;

public class smallchangeoop {
    public static void main(String[] args) {
        Mainmenuoop mainmenuoop = new Mainmenuoop();
        mainmenuoop.mainMenu();
    }
}

总结:
1.return;和break;作业没有记清楚
2.swich(){
case " " :
结构
3.Date date = null;
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm”);
data = new Data()
使用 sdf.format(data);
日期,和日期格式化
4.拼接信息的思想
5.while (true){
//用户必须输入y/n,否则就一直循环
System.out.println(“你确定要退出嘛(y/n)?”);
hint = scanner.next();
if (“y”.equals(hint) || “n”.equals(hint)){
break;
}
}
反向限制,考虑不符合的情况,简化代码
一个功能用一个模块来实现,方便以后扩展

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/149098.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Docker安装Nginx

基于Docker安装Nginx 1.安装Nginx 先启动一个 Nginx 实例, 可以得到相关配置 1.这里我将安装的软件放在/mydata目录下 #进入mydata目录 cd mydata/ #创建nginx目录 mkdir nginx # 拉取nginx 1.10版本镜像并允许容器 docker run -p 80:80 --name nginx -d nginx:1.10将容器内…

RHCE第四天之Web服务器详解

文章目录一、网址及HTTP简介二、www服务器的类型三、 www服务器的基本配置四、基于https协议的静态网站五、实验练习web服务器提供的数据大部分都是文件&#xff0c;那么我们需要在服务器端先将数据文件写好&#xff0c;并且放置在某个特殊的目录下面&#xff0c;这个目录就是我…

Profiler导致的严重性能问题

背景客户反馈系统突然运行非常缓慢&#xff0c;持续了近20分钟的时间&#xff0c;通过SQL专家云定位到有人开启了Profiler导致&#xff0c;但是不能定位是谁开启的&#xff0c;请我们协助分析。现象登录SQL专家云&#xff0c;进入实时可视化页面&#xff0c;在活动会话中看到在…

【Ctfer训练计划】——(十)

作者名&#xff1a;Demo不是emo主页面链接&#xff1a; 主页传送门创作初心&#xff1a;舞台再大&#xff0c;你不上台&#xff0c;永远是观众&#xff0c;没人会关心你努不努力&#xff0c;摔的痛不痛&#xff0c;他们只会看你最后站在什么位置&#xff0c;然后羡慕或鄙夷座右…

智公网:这几类人员报考公务员无法被录取

对于很多人来讲&#xff0c;毕业之后都想找一份稳定的工作&#xff0c;目前最受欢迎的就是公务员和教师编了&#xff0c;我们今天来说下公务员这个铁饭碗。 公务员考试可是很不容易的&#xff0c;有两场考试&#xff0c;第一场是笔试&#xff0c;第二场是面试。笔试通过之后才…

2021-06-10 Multisim的74LS192功能表及555时基74LS190

缘由https://ask.csdn.net/questions/7445811?spm1005.2025.3001.5141以及60s倒计时电路连接后没有显示 - 24小时必答区 74LS192芯片是一个具有双计数功能的芯片&#xff0c;既可以做加计数&#xff0c;也可以做减计数。 1、A、B、C、D 置数输入端&#xff0c;管脚悬空相当…

Web端接入视频设备(NVR/IPC)

概述 本文主要介绍视频监控设备&#xff0c;视频监控设备接入&#xff0c;常用的开源流媒体及接入过程中的一些问题。 第一章 视频监控设备 目前常见的视频监控设备主要有NVR和IPC&#xff0c;以海康为例。 1.1 视频监控设备介绍 IPC即IP Camera&#xff0c;可以接入网络的…

06-GC垃圾收集器有那些?

如图展示了HotSpot虚拟机中7种不同的垃圾收集, 连线代表两者可搭配使用 1.Serial 垃圾收集器&#xff08;单线程、复制算法&#xff09; Serial&#xff08;英文连续&#xff09;是最基本垃圾收集器&#xff0c;使用复制算法&#xff0c;曾经是JDK1.3.1 之前新生代唯一的垃圾…

【基础】Flink -- DataStream API

Flink -- DataStream API执行环境 Execution Environment创建执行环境设置执行模式触发程序执行源算子 Source从集合中读取数据从文件读取数据从 Socket 读取数据自定义数据源转换算子 Transformation基本转换算子映射 map过滤 filter扁平映射 flatMap聚合算子 Aggregation按键…

WPS配置mathtype

笔者电脑软件版本&#xff1a;WPS Office mathtype_7.4.8.0 请注意WPS适配的mathtype版本。 下载地址 mathtype_7.4.8.0&#xff1a;https://wwl.lanzoum.com/iuJDz0guffuh wps.vba.exe&#xff1a;https://handong1201.lanzouw.com/iX5GZtn70pe&#xff08;mathtype右侧选…

查找算法之线性查找

目录 线性查找 算法实现 算法实现 python C 复杂度分析 优点与缺点 线性查找 线性查找&#xff08;Linear Search&#xff09;是一种最基础的查找方法&#xff0c;其从数据结构的一端开始&#xff0c;依次访问每个元素&#xff0c;直到另一端后停止。 算法实现 线性查…

【凸优化】Gradient Descent and Newton Descent【梯度下降法和牛顿下降法】(含Python代码绘制等高线图)

文章目录Gradient Descent and Newton Descent一、下降法【Descent】二、梯度下降法【Gradient Descent】三、牛顿下降法【Newton Descent】四、示例Example五、ReferenceGradient Descent and Newton Descent 一、下降法【Descent】 首先介绍什么是下降法【Descent Methods】…

【Git】下载安装学习记录

【下载安装】 1.官网下载64位的安装包 2.双击安装&#xff0c;设置安装路径&#xff0c;一路next即可 使用学习指南&#xff1a;一、设置用户签名二、操作本地库的命令git initgit statusgit add 文件名git rm --cached 文件名git commit -m "注释" 文件名git refl…

在PyCharm中配置Anaconda环境

目录 1.创建项目 2.设置解释器 ​​​​​​ 3.常见问题 1.创建项目 2.设置解释器 3.常见问题 1.%matplotlib inline报错&#xff1a;Python关于%matplotlib inline 2.from d2l import torch as d2l报错&#xff1a; 报错原因&#xff0c;没有导入d2l这个包 如何导入呢&…

JDK8下载安装与配置环境变量(linux)

一、前言 基于Linux平台的MySQL安装文件有三个版本&#xff0c;分别是RPM软件、GenericBinaries软件包、源码包&#xff0c;具体介绍如下&#xff1a; ①RPM软件包是一种Linux平台下的安装文件&#xff0c;通过相关命令可以很方便地安装与卸载。该软件包分为两个&#xff1a;…

SVF Saber的实现

SVF Saber1.基本原理2.API类型定义3.Memory Leak Checker3.1.示例3.2.初始化3.3.程序切片3.4.路径约束求解3.5.报告错误4.总结5.参考文献Saber是一个静态漏洞检测器&#xff0c;最初集成到open64中&#xff0c;现已集成到SVF中&#xff0c;主要检测内存泄漏&#xff0c;DoubleF…

GAN的损失函数

1.GAN 在训练过程中&#xff0c;生成器和判别器的目标是相矛盾的&#xff0c;并且这种矛盾可以体现在判别器的判断准确性上。生成器的目标是生成尽量真实的数据&#xff0c;最好能够以假乱真、让判别器判断不出来&#xff0c;因此生成器的学习目标是让判别器上的判断准确性越来…

PCL点云处理之快速点特征直方图(FPFH)描述符(八十六)

PCL点云处理之快速点特征直方图(FPFH)描述符(八十六) 前言一、快速点特征直方图理论二、FPFH和PFH的区别二、实验过程1.代码2输入法线的NAN值检查用 OpenMP 加速 FPFH前言 对于具有 n 个点的给定点云 P,点特征直方图(见点特征直方图(PFH)描述符)的理论计算复杂度为 O (nk…

VueRouter路由的使用(上)

文章目录VueRouter路由的使用p21路由的原理_hash改变historyP22 认识vue-router路由的基本使用流程默认路径router-link路由懒加载路由的其他属性动态路由的基本匹配NotFound路由嵌套编程式导航VueRouter路由的使用 p21 路由的原理_hash改变 <!DOCTYPE html> <html …

JavaScript 运算符

文章目录JavaScript 运算符JavaScript 算术运算符JavaScript 赋值运算符用于字符串的 运算符对字符串和数字进行加法运算JavaScript 运算符 运算符 用于赋值。 运算符 用于加值。 运算符 用于给 JavaScript 变量赋值。 算术运算符 用于把值加起来。 实例 指定变量值&am…