5 面向对象
java是面向对象的(oop)语言
编程语言的发展
主线
- 以人为本(程序思维接近人的思维
- 代码的重用(怎么让代码重复使用
机器语言 可读性差,把人想象成机器 没用复用性
汇编语言(将简单英文替换及机器语言:可读性好 但需要懂硬件 代码复用差
高级语言:
面向过程语言:c语言,重点在过程,细节,对数据不是很关注
对整体的考虑,不适应
代码的重用层次: 函数级
面向对象编程语言: java, C#,python…
重点: 在整体, 在对象上, 这个对象包含数据,又包含的动作(函数/方法),
代码的重用层次: 类层次/对象层次
面向对象三大特征:
- 封装 (Encapsulation)
- 继承 (Inheritance)
- 多态 (Polymorphism)
类与对象
对象: 生活中,看得见,摸得着的具有的东西都是对象, 具体的
类: 一组相同的特征的对象的集合, 抽象的
对象与类的关系:
对象是类的实例化(具体化)
类是对象的抽象出来
类是模板, 对象通过这个模板创建出来的,
使用的对象,不是使用类
类定义语法:
public class 类名{
//定义属性部分
属性1的类型 属性1;
属性2的类型 属性2;
…
//定义方法部分
方法1;
方法2;
…
方法m;
}
一个类不一定有属性,也可以没有属性, 也不一定有方法
类名的规范:
- 类的第一个字母大写
- 遵循的大驼峰命名法
- 见名知意
- 不能使用关键
类的属性也叫类成员变量,类的方法也叫类的成员函数/成员方法。一个类中的方法可以直接访问同类中的任何成员(包括成员变量和成员函数)
属性定义语法:
[访问修饰符] 数据类型 属性名;
[] 在语法中表示可有可无
访问修饰符: 有四个: public 缺省(默认) protected private
属性名规范: 与变量名规范一样
- 首字母小写
- 遵循小驼峰命名法
- 不能使用关键字
- 见名知意
- 一个类的属性有无数多个, 到底写那些属性, 根项目需要存储对象那些属性来决定
测试类: 包含main方法的类
创建对象之前: 给对象的属性进行初始化操作
面向对象的内存结构图:
局部变量是保存在内存的栈中,而new出来的东西是保存在堆中
面向对象的思维写代码:
步骤:
- 考虑问题中包含几个对象, 有几类对象,表示有几个类
- 考虑每个对象包含那些属性
- 考虑每个对象包含那些方法, 计算总分方法, 计算平均分方法
对象数组
数组类型可以定义为对象
包
在Java中用包进行分类,在文件系统中就是文件夹
包名 公司名反写
例如: com.dodo.[项目名].模块名
包使用“.”分割
使用import导入
不需要导包:
- 若A类与B类位于同一个包 可以直接使用
- java.lang 下的包不用导入
若都不满足
则要用import导入 位置在class外面
import 包名 类名
使用通配符 ==*==则可以使用该包下所有类
访问修饰符
访问范围
public : 项目中的所有类
portected:同包和不同包子类
缺省:同包
private:同一个类
实际开发中 public和private常用
public:暴露给调用者使用
private:不让调用者使用,本类内部使用
方法
对对象的动态描述,表示这个对象拥有什么行为
方法是一段具有独立功能的代码
方法必须先创建才能使用,创建方法的过程叫方法的定义
方法创建功能后不会直接运行 需要调用才会执行
为什么要有方法
方法定义
[访问修饰符] 返回值类型 方法名([参数列表]){
方法体
}
访问修饰符:public 缺省的 protected private
返回值类型(8大),String以及其他的类类型
用void作为返回值类型,方法体不可以使用 return 结果
如果使用其他数据类型作为返回值,方法体一定要使用return 结果 返回
需要从实际考虑是否需要返回值
return关键字作用:
-
return
- 结束方法
-
return 结果 先返回结果 后结束方法
方法调用
执行方法体的代码 调用一次就执行一次
-
在main方法中调用,在其它类的方法调用
- 创建调用方法所在类的对象
- 使用对象.方法名()调用
-
在本类中其他方法调用
- 直接调用
调用有参方法一定要给参数
方法常见错误
- Java方法内部不能定义方法也不能定义属性
- 返回值类型不正确
- 方法不能嵌套
- 方法的返回值类型为void,表示该方法没有返回值,没有返回值的方法可以省略return语句不写,如果要编写return,后面不能跟具体的数据
方法重载
在**同一个类里 具有相同方法名 **的一组方法,但是参数列表不一样 与返回值无关
作用:具有相同功能的方法名 让开发者免去取名麻烦 调用者减少记忆
参数列表不一样:
- 参数个数不一样
- 对应位置数据类型不一样
- 参数名不一样是错误的
如何判断是否是相同方法:
1.看方法名是否一样
2.如果一样则判断是否参数列表一样,如果个数一样且对应位置参数类型一样,则是同个函数
jdk 不能同时存在两个相同的方法, 无法判断是否是相同方法
构造器/构造方法
要求:
- 方法名与类名一样
- 没有返回值这一说法
语法
[访问修饰符]类名([参数列表]){ //方法体 }
调用构造器: 返回创建的类的对象
通过new 关键字调用
new 构造方法();
如果手动编写了构造方法, JVM虚拟机就不会创建构造方法
this关键字
1.如果局部参数名与属性名一样,参数名优先,可以使用this.属性表示属性名区分局部变量与属性
2.this.方法名 在本类方法中调用其他本类方法
一般可以省略
3.this(参数)调用本类其他构造方法
1.只能在构造方法中使用
2.只能在第一行
idea自动生成构造方法:alt+insert
static关键字
可以修饰
-
属性: 静态属性 类属性
语法:static 数据类型 属性名
此时静态属性作为该类所有对象共享
调用静态属性
1)使用对象名.静态属性名
无法调用非静态资源
2)使用类名.静态属性名(推荐)
-
方法:静态方法 使用场景 :工具类
静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员方法),只能访问所属类的静态成员变量和成员方法。
注意
- 在静态方法里只能直接调用同类中其它的静态成员(包括变量和方法),而不能直接访问类中的非静态成员。对于非静态的方法和变量,需要先创建类的实例对象后才可使用,而静态方法在使用前不用创建任何对象。
- 静态方法不能以任何方式引用this和super关键字。因为静态方法在使用前不用创建任何实例对象,当静态方法被调用时,this所引用的对象根本就没有产生。
- main()方法是静态的,因此JVM 在执行main 方法时不创建main 方法所在的类的实例对象,因而在main()方法中,我们不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员。
-
静态代码块
一个类中可以使用不包含在任何方法体中的静态代码块(static block ),当类被载入时,静态代码块被执行,且只被执行一次,静态块经常用来进行类属性的初始化。
-
内部类
封装
1.封闭隐藏,隐藏细节,保护安全
2.包装,组装:整体的眼光看待问题
封装是 JAVA 面向对象的特点的表现,封装是一种信息隐蔽技术。它有两个含义:即把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位;以及尽可能隐藏对象的内部结构。也就是说,如果我们使用了封装技术的话,别人就只能用我们做出来的东西而看不见我们做的这个东西的内部结构了。
作用
-
提高易用性(使用简单)一个类内部可能很复杂,这些复杂代码封装起来
-
提高安全性:对于一些属性方法禁止用户访问提高安全性
-
把重复的代码抽取出来,使用的方法或者类来封装,从而达到代码的重复使用
Java封装的实现
步骤:
把该属性的访问修饰符号设为private(此资源只能在本类访问
给属性提供公开的get/set方法:get方法:读操作 set方法:写操作
private int age; public int getAge(){ return age; }
不直接修改参数保证数据的安全
继承
子类继承父类,子类继承父类属性方法,构造方法不能继承,但是如果父类这个属性由于private修饰,子类继承这个属性,但是无法访问
作用
实现代码的重用,基于类层次代码
继承使用步骤
-
把子类公共代码抽取出来,形成父类
-
让子类继承父类:
使用关键字extends
语法:
public class 子类 extends 父类 { }
继承的细节
- Java的继承是单继承,一个子类只能由一个直接父类 但能多层继承
子类对象实列过程
1.初始化父类属性
2.调用父类构造方法
3.初始化子类属性
4.执行子类构造方法
super
super表示父类的对象,this表示本类对象
super属性:调用父类属性,一般无法使用
super.方法:调用父类的方法
注意
- 只能写在子类构造方法内
- 只能在子类构造方法的第一行代码
- 不能与this() 同时存在
- 如果子类构造方法没有写super(), jvm会自动添加super(), 手动编写super()调用父类构造方法, jvm不会添加
super()
方法的重写
如果子类对父类/父辈类某个方法的实现(方法体)不满意,子类可以重新写方法体
重写特征:
1.子类重写父辈类方法
2.方法的方法名,参数列表与父类被重写的一样
3.子类重写方法的访问修饰符和父类被重写的访问修饰符一样,或者更低
4.子类重写方法返回值比父类被重写方法的返回值
在子类被重写的方法上添加@override注解,对父类重写的方法进行编译
idea重写快捷方式
ctrl+O
抽象类
限制这个类不能被实例化,只能被继承
语法
public abstract class 类名
包括
属性
普通方法
构造方法
抽象方法
一个抽象类一定包含抽象方法(X)可以包含也可以不包含,抽象方法一定位于抽象类和接口
抽象方法
父类定义一个方法,这个方法实现不重要,但子类一定要重写这个方法
子类不重写会报错
抽象方法作用:被子类重写
定义语法:publick abstract 方法名([参数列表]);
如果父类定义了抽象方法,
子类有两种解决方法:
1.让其子类继承
2.重写
抽象方法的细节
-
抽象方法不能用private修饰
-
不能用static修饰
-
不能用final修饰
final用来修饰 属性 变量 方法 类
1.修饰属性,给属性赋初值,属性的值不变
2.修饰方法 这个方法不能被重写
3.修饰类 这个类永远不能被继承
Java定义常量:
[public/private /其他修饰符] static final 数据类型
public 定义全局系统常量
命名规范:常量名全部大写 如果多个单词用_隔开
实际开发中使用的数字应该避免直接赋值
多态
对继承和重写的综合应用
生活中的多态:同一样事情给的工具环境不一样,得到的效果也不一样
所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定
程序中的多态:一个引用变量指向不同的实例,从而导致调用方法产生不同效果(子类重写方法),该方法具有多种运行状态
多态作用
实现代码重用, 让程序的扩展性得到提高
使用多态进行优化:
多态的体现:
- 父类类型作为方法的参数
- 父类类型作为方法返回值类型
多态的实现的前提条件:
- 有继承
- 方法重写
- 父类引用指向子类对象
方法重写:
如果子类重写父类的方法, 使用子类对象调用该方法, 调用子类重写的方法
向上转型
把子类转换为父类: 多态的实现的前提条件
自动转换, 父类类型 变量 = 子类对象;
优点: 实现多态,
缺点: 无法调用子类特有的属性和方法
向下转型
把父类转换为子类: 强制类型转换
子类类型 变量 = (子类)父类对象;
目的: 调用子类特有属性和方法
缺点: 可能出现ClassCastException 异常(转换的类型不匹配)
instanceof 关键字
语法:
对象名 instanceof 类名
结果: boolean
true: 表示这个对象 是类的对象或者是类子对象
false: 表示这个对象不是类的对象
向下转型, 请先使用instanceof 进行判断一下, 防止出现ClassCastException
接口
1.java使用接口简洁实现多继承,一个类使用实现多个无关紧要的接口
2.使用接口进行隔离 降低接口耦合度
低耦合高内聚
3.使用接口实现标准化
接口:一个更抽象的抽象类,接口中只能包含常量、抽象方法
class A implements a,b,x
- 接口能包含常量 不能包含属性(接口里的常量可以省略 public static final
- 没有构造方法,不能实例化
- 只能有抽象方法 pubilc abstract (也能省略)
可以定义一个没有任何抽象方法的接口,该接口作为一种标志,实现这个接口表示该类贴了这个标志
*一个不相关的类强转为不相关接口是可以的,语法上不报错
类 extends 类
类 implemens 接口1,接口2
接口 extends 接口1,接口2
类 extends 类 implements 接口
类名
结果: boolean true: 表示这个对象 是类的对象或者是类子对象 false: 表示这个对象不是类的对象
向下转型, 请先使用instanceof 进行判断一下, 防止出现ClassCastException
接口
1.java使用接口简洁实现多继承,一个类使用实现多个无关紧要的接口
2.使用接口进行隔离 降低接口耦合度
低耦合高内聚
3.使用接口实现标准化
接口:一个更抽象的抽象类,接口中只能包含常量、抽象方法
class A implements a,b,x
- 接口能包含常量 不能包含属性(接口里的常量可以省略 public static final
- 没有构造方法,不能实例化
- 只能有抽象方法 pubilc abstract (也能省略)
可以定义一个没有任何抽象方法的接口,该接口作为一种标志,实现这个接口表示该类贴了这个标志
*一个不相关的类强转为不相关接口是可以的,语法上不报错
类 extends 类
类 implemens 接口1,接口2
接口 extends 接口1,接口2
类 extends 类 implements 接口