面向对象 (基础篇)

ygcDiary / 2023-09-02 / 原文

面向对象(基础篇)

1. 概述

1.1 什么是面向对象

  • 面向对象关注的是:在计算机程序设计的过程中,参照现实的事物,将事物的属性特征、行为特征抽象出来,用类来表示。
  • 代码结构:以为组织单位,每种事物都具备自己的属性行为/功能
  • 是一种设计者思维,适合解决复杂问题,代码扩展性强,可维护性高。

1.2 面向对象内容的三条主线

  • JAVA类及;类的成员:(重点)属性方法、(熟悉)构造器、代码块,内部类。
  • 面向对象的三大特征:封装继承多态,(抽象)。
  • 其他关键字的使用:this、super、package、import、static、final、interface、abstract...等

1.3 面向对象完成具体功能的操作流程(重要)

  1. 创建类,设计类的内部成员(属性,方法)
  2. 创建类的对象例如Phone phone = new Phone();(类的实例化)
  3. 通过对象,调用类中定义的方法和属性实现具体的功能

2. 基本元素(类,对象)

2.1 类

  1. :具有相同特征的事物的抽象描述,是抽象的、概念上的定义。

设计类,其实就是设计类的成员

  1. 类的实例化

    • 等价描述:类的实例化<=>创建类的对象<=>创建类的实例

    • 格式:类的类型 对象名 = 通过new创建对象的实体

    • //创建一个对象
      Phone phone = new Phone();
      

2.2 类的内部成员

  • 成员之一:属性(成员变量,filed)
  • 成员至二:(成员方法)方法,(函数、method)

2.3 类的成员之一:属性(成员变量,filed)

  1. 变量的分类:
  • 角度一:按照数据类型,基本数据类型:8种。引用数据类型:(数组,类,枚举,注解,记录)
  • 角度二:按照定义的位置分类,成员变量(属性),局部变量(方法内,构造器内,代码块内)
  1. 属性的几个称谓:成员变量,filed,

  2. 区分成员变量 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.1 权限修饰符

  • public ,private,protect,缺省

    1.2 返回值类型:描述调用完此方法,是否需要返回一个结果

  • 无返回值:void

  • 有返回值:可以是基本数据类型,也可以是引用数据类型。

    • 在 有返回值 的类型中需要配合return+返回值类型的数据或常量
    • 【经验:】根据方法实现的功能,来判断是否需要返回值

​ 1.3 形参列表:是局部变量

  • 格式:(形参类型1 形参1,形参类型2 形参2,......)
  • 有形参:根据方法调用时不确定因素的个数,确定形参的个数
  • 无形参:不可以省略()
  1. return返回值
  • 作用1:结束一个方法
  • 作用2:结束方法的同时返回数据给方法的调用者
  • return后不能有执行语句

2.4.1 注意事项

  • JAVA中的方法,不调用不执行,调用一次,执行一次,在main开始之前,先在方法区加载类
  • 方法的定义不分先后顺序。在方法中可以调用其他的方法,不分前后。
  • 方法中可以调用方法或属性
  • 方法内不能定义方法,方法与方法是平级关系

举例:


2.4.2 方法的使用

  • System.out.println(employee1.show());无返回值报错,有返回值不报错


2.4.3 方法的内存结构

image-20230823115416674

2.4.4 方法的使用(练习)

2.4.4.1数组工具类

  • 数组工具类测试

2.4.5 方法的重载

在类中不允许定义相同的方法

  1. 定义:在同一个类中,允许存在多个重名,但参数列表不同的方法

  2. 两同一不同:

    • 两同:同一个中。方法名相同
    • 不同:参数列表不同
  3. 方法的重载与权限修饰符,形参名,返回值类型都没有关系

  4. 举例

    • 
      

      经典面试题

    • 
      

2.4.6 可变形参个数的方法

  1. 在定义方法时,形参类型确定,但是参数的个数不确定
  2. 格式:(参数类型...参数名)
  3. 可以构成重载(除了数组类型之外)
  4. 可以类比成数组
  5. 可变个数的形参必须放在参数列表的最后(int a,int...num)
  6. 可变个数的形参在同一个方法的参数列表,最多只能出现一次

举例:


  • 练习

2.4.7 递归方法

  1. 定义一个方法,方法自己调用自己
  2. 分类: 直接递归,间接递归
  3. 说明:
  • 递归方法是一种隐式的循环

  • 如果这种循环不能停止,则会报错(栈内存溢出)

  1. 递归调用会占用大量的系统堆栈,内存耗用多,在递归调用层次多时速度要比循环慢的多,所以在使用递归时要慎重。

  2. 在要求高性能的情况下尽量避免使用递归,递归调用既花时间又耗内存。考虑使用循环迭代

2.4.7.1 练习

2.6 值传递机制

2.6.1 基本数据类型和引用数据类型的值传递机制


2.6.2 方法的值传递机制

  • 实例引入

2.6.2.1 总结(不管是基本数据类型,引用数据类型,还是方法,都是值传递的机制)
  1. 对于方法内声明的变量,出现赋值操作,分为两种情况
  • 如果是基本数据类型的变量:直接赋数据
  • 如果是引用数据类型的变量:赋值操作,赋值的是地址值

2.6.4 练习






2. 7对象

对象:实际存在的该类事物,每个个体,是具体的,因此也称为实例(insrance)

2.7.1 对象在内存中分配涉及到的内存结构

  1. 栈:方法内定义的变量,存储在栈中。
  2. 堆:new出来的结构(比如:数组的实体,对象的实体)。包括对象的属性
  3. 方法区:存放类的字节码文件,(类的模板)

2..2 对象的内存解析

2..2.1 创建类的一个对象

image-20230822140844125

2..2.2 多个类的多个对象
image-20230822140646448

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 对象数组 (与二维数组类似)

  1. 什么是对象数组:
  • 数组中的数据可以是基本数据类型,也可以是引用数据类型,因此,数组中的元素全部为对象,称为对象数组
  1. 举例:
  • String[],Person[].....
  1. 案例


  1. 内存解析

image-20230823151412034

关键字

import:同名类导入,需要使用全类名的方式区分。

Date date = new Date();
java.sql.Date sqlDate = new java.sql.Date(123456);

3. 面向过程

3.1 什么是面向过程

  • 函数组织单位
  • 是一种执行者思维,适用于解决简单的问题。扩展能力差,不便于后期的维护。

4. 封装性

4.1 为什么需要封装性

  1. 高内聚,低耦合的体现:
  • 高内聚:类的内部数据和操作细节由自己完成,不允许外界干涉
  • 低耦合:仅仅暴露少量方法给外部使用。尽量方便外界调用。

高内聚、低耦合是软件工程中的概念,也是UNIX 操作系统设计的经典原则。

内聚,指一个模块内各个元素彼此结合的紧密程度;耦合指一个软件结构内不同模块之间互连程度的度量。内聚意味着重用和独立,耦合意味着多米诺效应牵一发动全身。

通俗的说:把该隐藏的隐藏,该暴露的暴露

4.2 如何实现数据封装

  1. 通过权限修饰符:
  • Java 提供了四个权限修饰符public,protected,缺省,private
  • 使用四种权限修饰符修饰类的内部成员,当这些成员被调用时体现可见性的大小
  1. 实际案例

说明:

  1. 在正常的条件下legs是不能小于0的,为了避免外部类赋值错误,我们可以将legs属性私有化,使外部类无法调用该属性,在内部类中可以提供一个暴露的方法,给外部类实现赋值操作
  2. 同时内部类也提供了一个暴露的方法,可以让外部类得到该属性的值
  3. 这就是数据的封装。

4.3 权限修饰符的范围

  • public > protected > 缺省 > private
修饰符 本类内部 本包内 其他包的子类 其他包非子类
private × × ×
缺省 × × ×
protected ×
public

4.4 四种权限的使用

4.1 权限修饰符的使用规则:

  1. 类:只能用public 和缺省修饰
  2. 类的内部成员:可以用4种权限修饰符修饰

4.2 使用频率

  1. 开发中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);

  1. 构造器的作用:
  • 搭配关键字new 创建类的对象
  • 在创建对象的同时,可以给相关的属性赋值
  1. 构造器的使用说明:
  • 构造器的格式
[修饰符] class 类名{
    [修饰符] 构造器名(){
    	// 实例初始化代码
    }
    [修饰符] 构造器名(参数列表){
        // 实例初始化代码
    }
}
  • 构造器名必须与它所在的类名必须相同

  • 没有返回值,所以不需要返回值类型,也不需要void

  • 构造器的修饰符只能是权限修饰符public,private,缺省,protected,不能是其他的

  • 创建类之后,在没有显示提供任何构造器的情况下,系统在编译时会自动提供一个空参的构造器

  • 默认的空参构造器的权限与该类的权限相同

  • 显示的创建了构造器,系统将不再提供默认的构造器

  • 构造器可以发生重载

  • 快捷键:在构建类的对象时,显示构造器的参数ctrl+p

5.2 举例



5.3 综合练习

  • 银行类

  • 用户类

  • 用户测试类

6. 类中的属性赋值的过程

  1. 类的属性有哪些赋值方式:

    • ① 默认赋值

    • ② 显示赋值

    • ③ 构造器赋值

    • ④ 对象.方法 赋值

    • ⑤ 对象.属性赋值

顺序是:① - ② - ③ - ④/⑤

  1. 其中 ① - ② - ③只能执行一次
  2. ④/⑤可以多次调用执行

7. JavaBean

JavaBean就是一个公共的类,里面含有一个无参构造器,和Get,Set方法。方便后期动态的创建对象

  • 所谓JavaBean,是指符合如下标准的Java类:

    • 类是公共的

    • 有一个无参的公共的构造器

    • 有属性,且有对应的get、set方法

  • JavaBean举例


8. UML类图

  • 在软件开发中,使用UML类图可以更加直观地描述类内部结构(类的属性和操作)以及类之间的关系(如关联、依赖、聚合等)。

    • +表示 public 类型, - 表示 private 类型,#表示protected类型

    • 方法的写法:
      方法的类型(+、-) 方法名(参数名: 参数类型):返回值类型

    • 斜体表示抽象方法或类。

image-20230826003425357