1.类图
1.1 类图说明
若要画上面的这种类图,推荐的工具有:
- processon.com:https://www.processon.com/
- PowerDesigner:可以设计数据库【抽取出表与表之间的关系、生成建表语句,支持多种数据库】、画各种流程图、类图
- StarUML:设计类图,生成java文件
- drwa.io:https://app.diagrams.net/ ----》你可以将图保存到github
1.2 对象在内存中的结构
回想我们之前的数组,都是引用类型,引用类型中有一个特殊String
2.成员变量vs局部变量【面试】
-
位置不同
①成员变量:在类中
②局部变量:在方法中,形参,代码块
-
初始值不同
①成员变量:有初始值,比如引用类型null,基本类型比如int 0
②局部变量:必须初始化,才能使用【必须显示赋值,才能使用】
-
作用范围不同
①成员变量:整个类中
②局部变量:它所在的
{}
范围 -
在内存中的区域不同
①成员变量:在堆内存中
②局部变量:在栈中
-
生命周期不同
①成员变量:随着对象的存在而存在,对象被标记为垃圾对象,需要一个过程,同时回收也需要一个过程
②局部变量:在栈中,用完之后就出栈
3.封装
3.1 为什么要使用封装
发现问题:
- 目前我们的属性可以随意赋值,有些值可能不合理,容易出现安全问题。
- 比如年龄1-100之间,在赋值的时候,加入判断逻辑
3.2 什么是封装
封装是我们面向对象三大特征之一。
将属性通过private
关键字进行修饰,即将属性私有化
3.3 原则
尽量将类的属性隐藏起来,通过方法进行赋值
注意:后面的实体类,全部使用封装
3.4 如何使用
- 属性私有化,即通过
private
修饰 - 提供公共的getXxx和setXxx方法进行取值和赋值(可以在set方法中加入判断逻辑)
快捷键:
alt+insert
若上面的快捷键不对,这么去找
练习:定义两个类Dog、Penguin
Dog:属性strain-品种、name-名字、health-健康值、love-亲密度
health、love范围[0-100]
方法:showInfo() —自我介绍
Penguin:属性sex-性别、name-名字、health-健康值、love-亲密度
health、love范围[0-100]
方法:showInfo() —自我介绍
上面的在写上全参构造和无参构造
测试类:从键盘输入值为属性赋值,分别创建dog和penguin对象,调用其showInfo()
4.包
4.1 为什么有包
理解为我们wins系统的文件夹
主要是使用层面
我们前面所有的类,都放在src目录的,有这么几个缺陷
- 不好管理,显得比较混乱
- 对于重名文件,就想使用一个名字,怎么办?放在不同的包
- 包一般我们按照业务去命名
4.2 如何使用
为了解决上面的问题,java为我们提供了包的机制
- 可以直接先创建包
- 创建类的同时建包
4.3 包的命名规范
- 包名小写
- 一般采用域名倒置,比如
taobao.com
,在使用包名的时候com.taobao.项目名.模块名称
4.4 如何导包
-
通过
import ...
,在package
的下面,类上面 -
特殊用法[了解]:在一个类中若想使用不同包下同名的两个类,有一个类需要通过全类名来使用
test02.Dog dog2 = new test02.Dog();
4.5 权限控制[笔/面试,低频]
public、protected、默认、private
位置 | public | protected | 默认 | private |
---|---|---|---|---|
同一个类 | √ | √ | √ | √ |
同一个包中的类 | √ | √ | √ | × |
不同包中的子类 | √ | √ | × | × |
不同包中的无关类 | √ | × | × | × |
5.基本类型值传递和引用类型传递
基本类型和引用类型,其实都值传递[即copy],基本类型是具体的数值的copy,而引用类型是地址值的copy
基本类型参数的值传递过程:
引用类型参数的值传递过程:
6.对象数组
需求:使用数组存放一批学生信息[stuNo、name、score],我们期望的是在数组中直接存放学生对象。若分数小于60,集体赠送2分。
分析:
- 明确:数组中可以存放任意数据类型
- 张三这个对象,它的数据类型是啥?张三是Stu类创建出来的,所以它的类型就是Stu
- 根据数组的定义:数据类型[] 数组名; ------> Stu[] stus;
对象数组的内存简图:
7.继承
7.1 概述
7.1.1 为什么要使用
前面的Dog和Penguin,有共同的属性【name、health、love】和showInfo(),如果我们将Dog和Penguin化为一类,假定都是Pet。比如,现在又来一个Cat【color、name、health、love】和showInfo()。
能否将共同的属性和方法提取出来,放到一个类中,这个类我们称之为父类【超类、基类】。
前提:子父类之间必须满足
is a
的关系
7.1.2 定义
面向对象的三大特征之一。
继承:子类继承父类的某些属性和行为,使得子类对象具有和父类相同的属性和行为。子类可以添加自己特有的属性和方法。
7.1.3 好处
- 提高代码的复用性。
- 让我们类与类之间建立了关系,是我们后面学习多态的基础。
7.2 继承的使用
- 创建一个父类,将共同的属性和方法写在父类中。
- 子类通过关键字
extends
,去继承父类
7.3 方法重写
思考:我们从父类继承过来的方法,并不符合我们子类的需求【输出4个属性的信息】,同时,我们又不想写一个别的方法【即我们还想用这个方法名】。需要对从父类继承过来的方法进行改造,我们称之为方法重写/覆盖。
- 与重载的区别
- 重写之后,子类再去调用,调用的是重写后的,还是继承过来的?重写后的
- 我们想调用父类方法,怎么调用?使用super
方法重写的特点:
- 前提:继承/实现
- 方法名相同、参数列表相同
- 返回值一样或是其子类
- 访问修饰符不能严于父类,比如父类用的是
protected
,子类重写的方法只能用protected或public
- 重写是多态的前提
【高频面试】重载 vs 重写
略
7.4 继承后的特点:成员变量
继承之后,对成员变量有什么影响
7.4.1 变量不重名
没有任何影响
7.4.2 重名
在子类中出现同名成员变量时,若要使用父类继承过来的,则使用super
调用;若使用子类自己的,可以使用this
7.5 继承后的特点:成员方法
7.5.1 成员方法不重名
没有任何影响,子类自己的特有方法。调用的时候,子类自己的方法
7.5.2 成员方法重名
参见 9.3
7.6 继承后的特点:构造方法
构造方法不能继承【若能继承,子类可以造爹】,但是我们子类在创建对象的时候,需要调用父类【先父后子,不是孙悟空】
this和super在调用构造方法的时候,不能共存!!!!因为,都要放在构造放的第一行!!!!
- 若子类没有通过super调用父类的构造方法,则默认调用父类的无参构造,然后在走子类自己的构造方法
- 若显示通过super调用父类的某个构造方法,则先走父类的这个构造方法,然后走子类构造
- 在子类中,若通过this显示调用自己的某个构造方法,先父在this(),然后再自身
7.7 super vs this
this:代表的是当前对象
super:父类
this:在当前类中使用,可以调用属性、方法、构造方法
super:在子类中使用,可以调用父类的调用属性、方法、构造方法
7.8 继承的特点
- 在java中,只支持单继承【只有一个亲爹】,也就是一个类只有一个直接父类
- 可以有多层继承:比如
B extends A
,C extends B
,但是A和B都称为C的父类 - 私有的、构造方法不能继承
8.抽象类【面试】
8.1 概述
8.1.1 由来
- 前面的showInfo,我们的父类并没有强制子类去实现
- 为父类,添加一个eat()方法,子类如何实现,父类不关心。父类关心的是有这么一个行为,即父类只定义方法的声明,不做实现。这种方法,我们称之为抽象方法。
- 另一方面,这样的,就可以实现1的目标,强制子类去重写抽象方法
8.1.2 定义
抽象方法:没有方法体,其他成分跟普通方法一样【修饰符、返回值类型、形参列表】
抽象类:抽象方法在抽象类中
8.2 语法
8.2.1 抽象方法
修饰符 abstract void eat(形参列表);
8.2.2 抽象类
abstract class Pet
8.2.3 抽象的使用
继承抽象类的子类,必须重写抽象方法,除非子类也是抽象类。
8.3 注意事项
-
抽象类能否直接创建对象?不能
理解:从语法层面,java不允许;从语义层面,若能new对象,那么就可以调用抽象方法,执行什么???
-
抽象类中可以有哪些成员?
普通类中有什么,抽象类中就可以有什么,而且抽象类还比普通类可以多抽象方法
- 构造方法:子类创建对象的时候,要先有父类
- 必须要有抽象方法吗?不是必须要有抽象方法
- 代码块
-
抽象类,一般专门用于继承
8.4 设计模式之模板方法
https://www.cnblogs.com/throwable/p/9315318.html
设计模式是代码经验的总结,设计模式可以让我们的代码写的更优雅、高效!23种设计模式
设计模式有7大原则:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-exJAk4Cr-1618381593665)(assets/image-20200416152613744.png)]
模板方式:即某个方法或代码的执行并不知道,此时我们只做声明(抽象方法),具体实现交给子类。
需求:计算某个方法的执行时间
- 编写一个模版类
public abstract class Template {
public void getTime() {
long statTime = System.currentTimeMillis();
//某个方法
print();
long endTime = System.currentTimeMillis();
System.out.println("耗时:"+(endTime-statTime));
}
public abstract void print();
}
- 编写子类
public class SubOneTemplate extends Template {
@Override
public void print() {
for (int i = 0; i < 1000; i++) {
System.out.println(i);
}
}
}
- 测试
public class TestTemplate {
public static void main(String[] args) {
// SubOneTemplate s1 = new SubOneTemplate();
// s1.getTime();
SubTwoTemplate s2 = new SubTwoTemplate();
s2.getTime();
}
}
需求:使用模板方法设计模式,完成去银行办理业务的过程
//1.区号
//2.排队
//3.business()
//4.走人
8.5 练习1-员工案例
8.5.1 需求
某IT公司有多名员工,按照员工负责的工作不同,进行了部门的划分(研发部员工、维护部员工)。
研发部根据所需研发的内容不同,又分为JavaEE工程师、Android工程师;
维护部根据所需维护的内容不同,又分为网络维护工程师、硬件维护工程师。
公司的每名员工都有他们自己的员工编号、姓名,并要做它们所负责的工作。
工作内容
JavaEE工程师:员工号为xxx的 xxx员工,正在研发淘宝网站
Android工程师:员工号为xxx的 xxx员工,正在研发淘宝手机客户端软件
网络维护工程师:员工号为xxx的 xxx员工,正在检查网络是否畅通
硬件维护工程师:员工号为xxx的 xxx员工,正在修复打印机
8.5.2 分析
画出继承体系图,并分析父类中应该定义什么属性和方法
9.Object类
Object是所有类的祖宗类。若一个类没有通过
extends
关键字显示继承某个类,则它的父类为Object类
9.1 主要方法
Object类中常用的方法,需要重写
-
toString
:输出属性值public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
观察String类的源码的toString
/**
* This object (which is already a string!) is itself returned.
*
* @return the string itself.
*/
public String toString() {
return this;
}
-
equals(Object obj)
跟hashCode()
一起重写对于引用类型而言,若没有重写equals方法,则使用equals等效于使用==
public boolean equals(Object obj) { return (this == obj); }
观察发现:String重写了equals方法
需求:假定两只Dog的名字一样,我们认为是同一只Dog,仿照String重写了equals方法
@Override
public boolean equals(Object o) {
//1.传进来的比对者是自己
if(this == o) {
return true;
}
//2.判断o类型是否Dog类型,instanceof
if(o instanceof Dog) {
//2.1 需要将大类型转为小类型
Dog dog = (Dog)o;
//2.2 假定两只狗的name一样,则为同一只
if(this.getName().equals(dog.getName())) {
return true;
}
return false;
}
//3.类型不一样
return false;
}
9.2 面试
10.练习
10.1 使用对象数组实现学生管理系统
-
使用对象数组实现学生管理系统,具体功能如下
学生的属性:stuNo,name,score,pwd 封装 ---->记录
方法:showInfo()
①登录[用户名+密码]、验证码[A-Za-z0-9],不区分大小写,随机生成四位,不去重
String genCode()
思路1:char[] chs = {‘A’…‘9’}
思路2://a----> 97
②登录进去主页面
1)添加学生:addStu(Stu stu,Stu[] stus)
2)修改学生:updateStu(Stu stu) ---->根据学号找 ----》写个查找的方法Stu getStuByStuNo(int stuNo)
至少修改2个值【score、pwd】----》从键盘输入
3)删除学生:delByStuNo(String stuNo)
4)显示学生信息列表:printStuInfo(Stu[] stus)
序号 学号 名字 分数
1 L1001 张三 100
5)分数统计 printScoreInfo(Stu[] stus)
最高分 最低分 平均分
100 60 80
有能力搞个排序:
6)退出
10.2 群主发普通红包
10.2.1 需求
群主发普通红包。某群有多名成员,群主给成员发普通红包。普通红包的规则:
-
群主的一笔金额,从群主余额中扣除,平均分成n等份,让成员领取。
-
成员领取红包后,保存到成员余额中。
请根据描述,完成案例中所有类的定义以及指定类之间的继承关系,并完成发红包的操作。
10.2.2 案例分析
10.2.3 代码实现
提示:
群主发红包,就是把一个整数的金额,分成若干等份。
1.获取群主余额,是否够发红包. 不能则返回null,并提示. 能则继续.
2.修改群主余额.
3.拆分红包.
3.1.如果能整除,那么就平均分。
3.2.如果不能整除,那么就把余数分给最后一份。
打开红包,就是从数组中,随机取出一份,保存到自己的余额中
10.3 继承相关
按要求实现下列问题:实现一个名为Person的类和它的子类Employee,Employee有两个子类Faculty和Staff。具体要求如下:
1)Person类中的属性有:姓名name(String类型),地址address(String类型),电话号码telphone(String类型)和电子邮件地址email(String类型);
2)Employee类中的属性有:办公室office(String类型),工资wage(double类型),受雇日期hiredate(String类型);
3)Faculty类中的属性有:学位degree(String类型),级别level(String类型);
4)Staff类中的属性有:职务称号duty(String类型)。
5)现有对象Person p1 =new Faculty()和Person p2 =new Staff (),请分别为p1的属性赋值“本科”和Staff类的duty赋值“职员”
10.4 找对象
- 通过媒婆搭线,实现男女婚介匹配
具体需求如下:
Boy:name、wealth、getAGirl(Girl girl)
Girl:name、faceValue、marryTo(Boy boy)
MeiPo:定义一个方法,双方先自我介绍一下【未截图】,若男wealth>1000且faceValue>100,则双
方都愿意,匹配成功
否则,肯定有一方条件不满足,或者双方都不满足