面向对象 (基础篇)
面向对象(基础篇)
1. 概述
1.1 什么是面向对象
- 面向对象关注的是
类
:在计算机程序设计的过程中,参照现实的事物,将事物的属性特征、行为特征抽象出来,用类来表示。 - 代码结构:以
类
为组织单位,每种事物都具备自己的属性
和行为/功能
- 是一种
设计者思维
,适合解决复杂问题,代码扩展性强,可维护性高。
1.2 面向对象内容的三条主线
- JAVA类及;类的成员:(重点)
属性
、方法
、(熟悉)构造器、代码块,内部类。 - 面向对象的三大特征:
封装
,继承
,多态
,(抽象)。 - 其他关键字的使用:this、super、package、import、static、final、interface、abstract...等
1.3 面向对象完成具体功能的操作流程(重要)
- 创建类,设计类的内部成员(属性,方法)
- 创建类的对象例如
Phone phone = new Phone();
(类的实例化) - 通过对象,调用类中定义的方法和属性实现具体的功能
2. 基本元素(类,对象)
2.1 类
类
:具有相同特征的事物的抽象描述,是抽象的
、概念上的定义。
设计类,其实就是设计类的成员
-
类的实例化
-
等价描述:类的实例化<=>创建类的对象<=>创建类的实例
-
格式:类的类型 对象名 = 通过new创建对象的实体
-
//创建一个对象 Phone phone = new Phone();
-
2.2 类的内部成员
- 成员之一:
属性
(成员变量,filed) - 成员至二:(成员方法)
方法
,(函数、method)
2.3 类的成员之一:属性(成员变量,filed)
- 变量的分类:
- 角度一:按照数据类型,基本数据类型:8种。引用数据类型:(数组,类,枚举,注解,记录)
- 角度二:按照定义的位置分类,成员变量(属性),局部变量(方法内,构造器内,代码块内)
-
属性的几个称谓:
成员变量
,filed, -
区分
成员变量
vs局部变量
3.1 相同点:
- 都是变量,符合变量的定义规范
- 必须先定义后使用
- 有各自的
作用域
,出了作用域就失效
3.2 不同点:
① 类中声明的位置的不同:
- 成员变量声明在
类
里 - 局部变量声明在
方法
里
② 在内存中分配的位置不同:
- 成员变量存放在
堆
中 - 局部变量存储在
栈
中
③ 生命周期:
-
成员变量:随着
对象
的创建而创建 -
局部变量:随着方法的
栈帧
进入栈中被激活,随着方法的栈帧出栈消亡
④ 作用域:
-
成员变量:作用在
整个类
中 -
局部变量:只作用在定义局部变量的方法或构造器,代码块中
⑤ 是否可以有权限修饰符进行修饰:
- public,protect,缺省,private
- 只有
成员变量
可以被权限修饰符
修饰
⑥ 是否有默认值:
- 成员变量:具有初始值,与
数组的初始值
相同 - 局部变量:没有初始值,定义时必须赋给初始值,才能使用,否则会报错
- 注意:对于
方法
的形参而言,在调用方法
时,给此形参赋值即可。
public void sleep(int hour) {
System.out.println("人每天至少睡眠" + hour + "小时");
}
//在调用方法时给huor赋值,不赋值无法调用方法
p1.sleep(8);
2.3.1 任何一个数据类型都可以是成员变量的类型。
- 举例
2.4 类的成员之二:方法(method)
- 方法是类或对象行为的抽象,用来完成具体的功能
- 将功能封装在方法里面,可以
实现代码的重用,减少代码的冗余,简化代码
- JAVA中方法不能
单独存在
,必须声明在类中 - 方法在使用完成之后就出栈。
-
方法的声明
权限修饰符 [其他修饰符] 返回值类型 方法名(形参列表){ //方法体 } //[其他修饰符]不是必须要写的
1.1 权限修饰符
-
public ,private,protect,缺省
1.2 返回值类型:描述调用完此方法,是否需要返回一个结果
-
无返回值:void
-
有返回值:可以是基本数据类型,也可以是引用数据类型。
- 在 有返回值 的类型中需要配合
return+返回值类型的数据或常量
- 【经验:】根据方法实现的功能,来判断是否需要返回值
- 在 有返回值 的类型中需要配合
1.3 形参列表:是局部变量
- 格式:(形参类型1 形参1,形参类型2 形参2,......)
- 有形参:根据方法调用时
不确定因素的个数
,确定形参的个数 - 无形参:不可以省略()
- return返回值
- 作用1:结束一个方法
- 作用2:结束方法的同时返回数据给方法的调用者
- return后
不能有执行语句
2.4.1 注意事项
- JAVA中的方法,不调用不执行,调用一次,执行一次,在main开始之前,先在
方法区
加载类 - 方法的定义不分先后顺序。在方法中可以调用其他的方法,不分前后。
- 方法中可以调用方法或属性
- 方法内不能定义方法,方法与方法是平级关系
举例:
2.4.2 方法的使用
System.out.println(employee1.show());无返回值报错,有返回值不报错
2.4.3 方法的内存结构
2.4.4 方法的使用(练习)
2.4.4.1数组工具类
- 数组工具类测试
2.4.5 方法的重载
在类中不允许定义相同的方法
-
定义:在同一个类中,允许存在多个重名,但参数列表不同的方法
-
两同一不同:
- 两同:同一个
类
中。方法名
相同 - 不同:
参数列表
不同
- 两同:同一个
-
方法的重载与
权限修饰符,形参名,返回值类型
都没有关系 -
举例
-
经典面试题
-
2.4.6 可变形参个数的方法
- 在定义方法时,形参类型确定,但是参数的个数不确定
- 格式:
(参数类型...参数名)
- 可以构成
重载
(除了数组类型之外) - 可以类比成
数组
- 可变个数的形参必须放在参数列表的
最后
(int a,int...num) - 可变个数的形参在同一个方法的参数列表,最多只能
出现一次
举例:
- 练习
2.4.7 递归方法
- 定义一个方法,方法自己调用自己
- 分类: 直接递归,间接递归
- 说明:
-
递归方法是一种隐式的循环
-
如果这种循环不能停止,则会报错(栈内存溢出)
递归调用会占用大量的系统堆栈,内存耗用多,在递归调用层次多时速度要比循环
慢的多
,所以在使用递归时要慎重。在要求高性能的情况下尽量避免使用递归,递归调用既花时间又
耗内存
。考虑使用循环迭代
2.4.7.1 练习
2.6 值传递机制
2.6.1 基本数据类型和引用数据类型的值传递机制
2.6.2 方法的值传递机制
- 实例引入
2.6.2.1 总结(不管是基本数据类型,引用数据类型,还是方法,都是值传递的机制)
- 对于方法内声明的变量,出现赋值操作,分为两种情况
- 如果是基本数据类型的变量:直接赋
数据
- 如果是引用数据类型的变量:赋值操作,赋值的是
地址值
2.6.4 练习
2. 7对象
对象
:实际存在的该类事物,每个个体
,是具体的
,因此也称为实例(insrance)
。
2.7.1 对象在内存中分配涉及到的内存结构
- 栈:方法内定义的变量,存储在栈中。
- 堆:new出来的结构(比如:数组的实体,对象的实体)。包括对象的属性
- 方法区:存放类的字节码文件,(类的模板)
2..2 对象的内存解析
2..2.1 创建类的一个对象
2..2.2 多个类的多个对象
2..3 注意事项
Person p1 = new Person();
Person p2 = new Person();
//创建两个对象
- 创建类的多个对象时,每个对象在堆空间中有一个对象的实体,每个对象的实体保存着一份属性
- 如果修改对象的某个属性时不会影响其他对象的属性
【相互独立】
Person p1 = new Person();
Person p3 = p1;//赋值操作
//创建一个对象
- 此时相当于将p1的地址值赋值给p3,在堆空间没有开辟新的空间存储新的对象属性,而是p1,p3公用一个对象的属性
- 此时通过p3修改对象的属性,p1相对应的属性也会被修改。
2..4 对象数组 (与二维数组类似)
- 什么是对象数组:
- 数组中的数据可以是基本数据类型,也可以是引用数据类型,因此,数组中的元素全部为对象,称为对象数组
- 举例:
- String[],Person[].....
- 案例
- 内存解析
关键字
import:同名类导入,需要使用全类名
的方式区分。
Date date = new Date();
java.sql.Date sqlDate = new java.sql.Date(123456);
3. 面向过程
3.1 什么是面向过程
- 以
函数
组织单位 - 是一种
执行者思维
,适用于解决简单的问题。扩展能力差,不便于后期的维护。
4. 封装性
4.1 为什么需要封装性
- 高内聚,低耦合的体现:
- 高内聚:类的内部数据和操作细节由自己完成,不允许外界干涉
- 低耦合:仅仅暴露少量方法给外部使用。尽量方便外界调用。
高内聚、低耦合是软件工程中的概念,也是UNIX 操作系统设计的经典原则。
内聚,指一个模块内各个元素彼此结合的紧密程度;耦合指一个软件结构内不同模块之间互连程度的度量。内聚意味着重用和独立,耦合意味着多米诺效应牵一发动全身。
通俗的说:把该隐藏的隐藏,该暴露的暴露
4.2 如何实现数据封装
- 通过权限修饰符:
- Java 提供了四个权限修饰符public,protected,缺省,private
- 使用四种权限修饰符修饰类的内部成员,当这些成员被调用时
体现可见性的大小
- 实际案例
说明:
- 在正常的条件下legs是不能小于0的,为了避免外部类赋值错误,我们可以将legs属性私有化,使外部类无法调用该属性,在内部类中可以提供一个
暴露的方法
,给外部类实现赋值操作 - 同时内部类也提供了一个
暴露的方法
,可以让外部类得到该属性的值 - 这就是数据的封装。
4.3 权限修饰符的范围
- public > protected > 缺省 > private
修饰符 | 本类内部 | 本包内 | 其他包的子类 | 其他包非子类 |
---|---|---|---|---|
private | √ | × | × | × |
缺省 | √ | × | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
4.4 四种权限的使用
4.1 权限修饰符的使用规则:
- 类:只能用public 和缺省修饰
- 类的内部成员:可以用4种权限修饰符修饰
4.2 使用频率
- 开发中4种权限修饰使用频率
- 比较高:public,private
- 不常用:缺省,protected
4.3 封装性的体现
-
私有化(private)属性,通提供公共的(public)get(),set()方法,对这个属性进行修改和获取
-
将类种不需要对外暴露的方法私有化
-
单例模式构造器私有化,避免在类的外部创建实例
4.4.1 练习
4.4.1.1 练习1,封装员工属性,并在键盘输入信息
5. 构造器(constructor)
凡是一个类,他都有自己的构造器
5.1 构造器概述
new对象,并在new对象的时候为实例变量赋值。
举例:Person p = new Person(“Peter”,15)
;
- 构造器的作用:
- 搭配关键字new 创建类的对象
- 在创建对象的同时,可以给相关的属性赋值
- 构造器的使用说明:
- 构造器的格式
[修饰符] class 类名{
[修饰符] 构造器名(){
// 实例初始化代码
}
[修饰符] 构造器名(参数列表){
// 实例初始化代码
}
}
-
构造器名必须与它所在的
类名
必须相同
。 -
它
没有返回值
,所以不需要返回值类型,也不需要void
。 -
构造器的修饰符只能是
权限修饰符
public,private,缺省,protected,不能是其他的 -
创建类之后,在没有显示提供任何构造器的情况下,系统在编译时会自动提供一个
空参的构造器
-
默认的空参构造器的权限与该类的权限相同
-
显示的创建了构造器,系统将不再提供默认的构造器
-
构造器可以发生重载
-
快捷键:在构建类的对象时,显示构造器的参数
ctrl+p
5.2 举例
5.3 综合练习
- 银行类
- 用户类
- 用户测试类
6. 类中的属性赋值的过程
-
类的属性有哪些赋值方式:
-
① 默认赋值
-
② 显示赋值
-
③ 构造器赋值
-
④ 对象.方法 赋值
-
⑤ 对象.属性赋值
-
顺序是:① - ② - ③ - ④/⑤
- 其中 ① - ② - ③只能执行一次
- ④/⑤可以多次调用执行
7. JavaBean
JavaBean就是一个公共的类,里面含有一个无参构造器,和Get,Set方法。方便后期动态的创建对象
-
所谓JavaBean,是指符合如下标准的Java类:
-
类是公共的
-
有一个无参的公共的构造器
-
有属性,且有对应的get、set方法
-
-
JavaBean举例
8. UML类图
-
在软件开发中,使用
UML类图
可以更加直观地描述类内部结构(类的属性和操作)以及类之间的关系(如关联、依赖、聚合等)。-
+表示 public 类型, - 表示 private 类型,#表示protected类型
-
方法的写法:
方法的类型(+、-) 方法名(参数名: 参数类型):返回值类型 -
斜体表示抽象方法或类。
-