3、面向对象

面向对象,主讲:汤小洋

一、面向对象简介

1. 什么是面向对象

OOP:Object Oriented Programming 面向对象编程

面向对象是一种程序的设计范型,是一种思想,使用对象的概念进行程序设计

一切皆对象:世间的万事万物都是对象

2. 两个概念

2.1 类

类是具有相同特征和行为的一组对象的抽象

类是一个抽象的概念,没有具体实物与之对应,如人类、动物、电脑等

2.2 对象

对象是类的实例

对象是某一个具体的事物,如这个学生、这只狗、这台电脑

3. 产生

记录马路上的汽车信息——>需要一个汽车类型,便于存储信息

自定义一个数据类型

二、类的使用

1. 定义类

语法:

class 类名
{
成员属性;  
成员方法;
}

类:

  • 一个类就是一个数据类型,定义一个类其实就是创建了一种数据类型

  • 类名使用帕斯卡命名法,即所有单词首字母大写

  • 一个文件中可以定义多个类,但只能有一个public修饰的类,且此类的名称必须与文件名相同

属性:

  • 表示类的特征

  • 定义方式:数据类型 属性名;

  • 属性名使用驼峰命名法,即第一个单词首字母小写,其他单词首字母大写

方法:

  • 表示类的行为

  • 定义方式:public 返回值类型 方法名(参数列表){ 方法体 }

  • 方法名使用驼峰命名法,且一般多使用动词

2. 创建对象

语法:

//方式1
类名 对象名 = new 类名();
//方式2
类名 对象名;
对象名 = new 类名();

3. 访问对象

访问对象的属性:对象名.属性名

访问对象的方法:对象名.方法名()

三、this关键字

1. 全局变量和局部变量

全局变量:

  • 在类中定义的变量,称为全局变量,也就是属性

  • 在整个类中都可以访问

  • 有默认值,可以直接使用

局部变量:

  • 除全局变量以外的其他变量,称为局部变量,如在方法或代码块中定义的变量

  • 只能在局部访问,如方法中或代码块中

  • 没有默认值,必须先赋值才能使用

  • 局部变量和全局变量可以同名,局部变量优先级更高,即默认访问的是局部变量

可以使用this关键字来解决局部变量和全局变量同名的问题

2. this用法

this表示当前类的一个对象

  • 只能在类的方法中使用,表示方法的调用者,即调用该方法的对象

  • 当局部变量和全局变量同名时,可以使用this.来访问全局变量

  • 当局部变量和全局变量不同名时,可以省略不写this.

四、static关键字

static表示静态的,可以用来修饰变量和方法,分别称为静态变量和静态方法

1. 静态变量

使用static修饰的变量,称为静态变量 或 类变量(非static修饰的变量称为实例变量)

静态变量为类的所有对象共有,属于整个类

访问方式:对象名.属性名类名.属性名(推荐)

2. 静态方法

使用static修饰的方法,称为静态方法 或 类方法(非static修饰的方法称为实例方法)

访问方式:对象名.方法名()类名.方法名()(推荐)

静态方法中只能访问静态变量或静态方法,不能访问实例变量和实例方法(实例方法中可以访问静态变量)

静态方法中不能使用this关键字,因为this表示当前类的某个对象,而静态方法并不属于某个特定的对象

 

变量分类

  • 从作用域上划分:全局变量、局部变量

  • 从变量所属上划分:实例变量、类变量

 

练习:对象数组

五、方法重载

一个类中包含两个或两个以上同名的方法,其参数不同,称为方法重载 overload

  • 在同一个类中

  • 方法名相同

  • 参数列表不同(参数个数、类型、顺序至少有一项不同),即方法签名不同

  • 与方法修饰符、返回值类型、形参名无关

作用:提供同一种功能的多种实现方式,根据调用者传递的参数来决定采用哪种方式

六、构造方法

构造方法是一种特殊的方法,也称为构造函数 或 构造器 constructor

作用:用于创建和初始化对象

特点:

  • 方法名必须和类名相同

  • 没有返回值,也不能写作void

  • 当创建类的对象时,会自动调用构造方法

  • 一个类中至少有一个构造方法,也可以有多个(构造方法重载)

  • 如果没有自定义构造方法,则类中默认会有一个无参的构造方法

  • 如果自定义了构造方法,则默认的无参构造方法就没有了,可以自己写无参的构造方法(建议)

  • 可以使用this(参数) 调用当前类中的其他构造方法,但只能出现在构造方法的第一行,即必须是第一条语句

七、包package

包的作用:

  • 区分同名的类

  • 类较多时便于管理

  • 便于访问控制

声明包:

  • 用来指定当前类所属的包

  • 使用package,写法:package 包名;

  • 必须位于第一行(注释除外)

命名规范:

  • 采用组织的反向域名,如com.baidu.fanyi

  • 使用小写字母,不能以点号开头或结尾

导入包:

  • 当需要使用其他包中的类时必须导入

  • 使用import,写法:import 包名.类名;import 包名.*;

  • 必须位于包声明的下面

  • 不能同时导入不同包下的同名类,如java.util.Date和java.sql.Date

常用的包:

  • java.lang 包含Java的核心类,如System、String、Math等,该包默认会被自动导入,当使用其中的类时,无需import导入

  • java.util 包含实用的工具类,如Scanner、Arrays等

  • java.io 包含输入/输出操作的类

  • java.sql 包含数据库操作的类

  • java.net 包含网络操作的类

  • java.awt 包含图形窗口操作的类

注:定义类时务必指定包名,严禁将类直接放到src下(default package 默认包),会导致该类无法被引用

八、访问修饰符

用来控制访问范围

修饰符同一个类同一个包内的类不同包内的子类不同包并且不是子类
public(公开的)
protected(受保护的)
默认
private(私有的)

总结:

  • public:在哪都能访问

  • protected:只有不同包并且非子类不能访问,其他都能访问

  • 默认:只有本包中可以访问

  • private:只有本类中可以访问

范围从大到小的顺序:public>protected>默认>private

九、对象的初始化顺序

1. 类加载

概念:将class文件读取加载到JVM内存中的过程,称为类加载

类加载的时机:

  1. 创建类的对象

  2. 调用类的静态属性或静态方法

  3. 通过反射调用类Class.forName("包名.类名")

  4. 执行main方法时,main方法所在的类会被加载

注:每个类只会被加载一次!!

2. 类的成员

类中的成员有:

  • 属性(实例属性、静态属性)

  • 方法(实例方法、静态方法)

  • 构造方法

  • 代码块

  • 静态代码块:使用static修饰的代码块

注:static关键字可以修饰变量、方法、代码块、匿名类等

3. 初始化流程

步骤:

  1. 对象所在的类被加载

    执行静态属性和静态代码块(根据定义的顺序,从上往下执行)

    特性:

    • 静态变量在类加载时初始化,且在内存中只分配一块空间

    • 静态代码块在类加载时执行,且只执行一次,主要用于初始化静态变量

    • 静态代码块不能初始化实例变量,只能初始化静态变量

  2. 对象被创建

    执行实例属性和代码块(根据定义的顺序,从上往下执行)

    执行构造方法

总结:执行先后顺序为静态代码块>代码块>构造方法

十、面向对象三大特征

1. 封装

1.1 Java代码规范

  • 将类的属性封装在类中,不允许在类的外部直接访问,保护数据的安全,使内容可控

  • 只能通过被授权的方法才能对数据进行访问

  • 类的基本原则就是封装​

1.2 实现方式

步骤:

  1. 将属性私有化

    使用private修饰属性

  2. 提供对外访问的方法,用于赋值、取值

    使用public修饰方法

    方法名的命名规范:

    • 取值方法:以get开头,后跟属性名,如getXxx,称为gettter方法(属性名首字母大写,采用驼峰命名法)

      如果是boolean类型属性,可以是getXxx, 也可以是 isXxx

    • 赋值方法:以set开头,后跟属性名,如setXxx,称为setter方法

    如果属性只具有getter方法,则表示该属性是只读的,在外部只能读取

    如果属性只具有setter方法,则表示该属性是只写的,在外部只能修改

一般都通过开发工具自动生成getter/setter方法

2. 继承

2.1 概念

可以让一个类继承自另一个类,此时该类会继承另一个类中的属性和方法

继承而得到的类称为子类(派生类),被继承的类称为父类(超类/基类)

继承是一种is a的关系,比如:Cat is a Animal——>猫是动物Student is a Person——>学生是人

2.2 实现方式

语法:

class 子类 extends 父类 {
   
}

作用:

  • 代码复用:将多个子类中相同的属性和方法放到父类中

  • 功能扩展:子类可以有自己独特的属性和方法

特性:

  • Java只支持单继承,不支持多继承,但支持多层继承,即继承的传递

  • Java中所有的类都直接或间接地继承了java.lang.Object类(后面会详细讲)

2.3 继承的范围

子类可以继承父类的哪些成员?

  1. 父类的public、proctected的属性和方法可以被子类继承

  2. 父类的默认修饰符的属性和方法在同包的情况下可以被子类继承

  3. 父类的private的属性和方法不能被子类继承

  4. 父类的构造方法不能被子类继承(原因:构造方法名必须与类名相同,而子类名称不可能与父类名称相同)

2.4 构造方法的调用

调用过程:

  • 创建子类对象时默认会自动调用父类无参的构造方法(此时必须要保证父类中有无参构造,否则会报错)

  • 从子类开始,逐层往上调用父类的构造方法,直至Object类,然后再层层返回到子类中,执行后续代码

  • 创建子类对象时必然会调用父类的构造方法,而调用父类构造方法也就创建了父类的对象,所以当创建子类对象时,其实也创建了父类对象,只不过这个父类对象并不是独立存在的,而是和子类对象合为一个整体

  • 可以使用super()显式指定调用父类的某个构造方法

super关键字:

  • 表示父类对象的引用,只能在子类中使用

  • 可以使用super()访问父类的构造方法,必须位于第一行

  • 可以使用super.访问父类的属性和方法,解决父类和子类中成员同名的问题

this关键字:

  • 表示当前对象的引用,只能在方法中使用

  • 可以使用this()调用本类中重载的构造方法,必须位于第一行

  • 可以使用this.访问本类中的属性和方法,解决全局变量与局部变量同名的问题

注:调用构造方法时this()和super()都只能放在第一行,所以不能同时使用

2.5 方法的重写

子类中方法,与父类中方法的名称、参数列表、返回类型一样,我们就说子类重写了父类的方法,称为方法重写override

  • 在父子类中

  • 方法名相同

  • 参数列表相同

  • 返回类型相同或是其子类

  • 访问修饰符不能缩小,即访问权限不能缩小

  • 子类不能抛出比父类更大的异常(后面会讲解)

作用:用来重新定义子类的行为,解决父类和子类的差异性

面试:方法重载与方法重写的区别

3. 多态

3.1 概念

多态是具有表现多种形态的能力的特征,即一种事物,具有多个形态

回顾?基本数据类型之间的转换:

  • 自动类型转换

  • 强制类型转换

引用类型之间的转换

3.2 引用类型之间的转换

两种:

  • 自动类型转换

    将子类对象转换为父类,如student——>Person

    将父类的引用指向子类的对象,称为向上转型,会自动进行类型转换

    特性:

    通过父类引用变量调用的方法是子类重写的方法,不是父类的方法

    通过父类引用变量无法访问子类特有的属性和方法

  • 强制类型转换

    将一个指向子类对象的父类引用赋给一个子类的引用,称为向下转型,必须进行强制类型转换

    语法:­(子类类型)指向子类的父类对象

    特性:

    向下转型后,可以访问子类特有的属性和方法

    必须转换为父类指向的真实子类类型,否则会出现类型转换异常ClassCastException

    向下转型是不安全的,可以在转换前使用instanceof操作符判断对象的类型,避免类型转换异常

3.3 多态的实现

将父类作为方法形参,将子类的对象作为方法实参,从而实现多态

案例:主人与宠物:玩耍、喂养

  • 主人类 Master

  • 宠物 Pet——>Dog、Cat(可扩展Pig)

  • 食物 Food——>Bone、Fish

3.4 总结

实现多态的条件:

  • 继承的存在(继承是多态的基础,没有继承就没有多态)

  • 子类重写父类的方法(多态下调用的是子类重写后的方法)

  • 父类引用变量指向子类对象(子类到父类的类型转换)

多态的优点:

  • 减少代码量

  • 提高可扩展性和可维护性

  •  

 

 

 

posted @ 2023-03-17 16:22  大冶  阅读(45)  评论(0)    收藏  举报