一、面向对象的概念
(一) 面向对象和面向过程的区别
面向过程 | 面向对象 | |
---|---|---|
强调的是功能行为 | 将功能封装进对象,强调具备了功能的对象。 | |
出发点 | 强调过程(的抽象化与模块化) | 强调问题(域的要领映射到对象及对象之间的接口上) |
层次逻辑关系 | 表达过程,用模块的层次结构概括模块或模块间的关系与功能,来抽象客观世界的问题,基本单位是模块 | 表达对象,用计算机逻辑来模拟客观世界中的物理存在,以对象的集合类作为处理问题的基本单位 |
数据处理方式 | 直接通过程序处理数据,处理完毕后即可显示处理结果 | 数据与对应的代码封装成一个整体,原则上对象的修改只能由自身的成员函数完成 |
控制程序方式 | 按照设计调用或返回程序,不能自由导航,各模块之间存在着控制与被控制、调用与被调用的关系。 | 通过“事件驱动”来激活和运行程序 |
分析设计与编码转换方式 | 强调分析、设计及编码之间按规则进行转换,贯穿于软件生命周期的分析、设计及编码中 | 从分析到设计再到编码是采用二致性的模型表示,贯穿于软件生命周期的分析、设计及编码中 |
- 面向对象是基于面向过程的。
(二) 面向对象的特点
是一种符合人们思考习惯的思想
可以将复杂的事情简单化
将程序员从执行者转换成了指挥者
完成需求时:
• 先要去找具有所需的功能的对象来用。
• 如果该对象不存在,那么创建一个具有所需功能的对象。
• 这样简化开发并提高复用。
(三)面向对象开发,设计,特征
OOA 面向对象分析
OOD 面向对象设计
OOP 面向对象语言
开发的过程:其实就是不断的创建对象,使用对象,指挥对象做事情。
设计的过程:其实就是在管理和维护对象之间的关系。
面向对象的特征:
• 封装(encapsulation)
• 继承(inheritance)
• 多态(polymorphism)
(四)优点
- 较高的开发效率。
- 保证软件的鲁棒性。
- 保证软件的高可维护性。
二、类与对象的关系
- 使用计算机语言就是不断的在描述现实生活中的事物。
- java中描述事物通过类的形式体现,类是具体事物的抽象,概念上的定义。
- 对象即是该类事物实实在在存在的个体。
(一)类与对象
- 现实对象抽象为类
- 类的实例化为对象
(二)类的定义
- 生活中描述事物无非就是描述事物的属性和行为。
• 如:人有身高,体重等属性,有说话,打球等行为。 - Java中用类class来描述事物也是如此
• 属性:对应类中的成员变量。
• 行为:对应类中的成员函数。 - 定义类其实在定义类中的成员(成员变量和成员函数)。
(三)成员变量和局部变量的区别
成员变量 | 局部变量 |
---|---|
成员变量定义在类中,在整个类中都可以被访问。 | 局部变量只定义在局部范围内,如:函数内,语句内等。 |
成员变量随着对象的建立而建立,存在于对象所在的堆内存中。 | 局部变量存在于栈内存中。 |
成员变量有默认初始化值。 | 作用的范围结束,变量空间会自动释放。 |
局部变量没有默认初始化值。 |
(四)匿名对象
- 匿名对象是对象的简化形式
- 匿名对象两种使用情况
• 当对对象方法仅进行一次调用的时候
• 匿名对象可以作为实际参数进行传递
三、封装(Encapsulation)
封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:
• 将变化隔离。
• 便于使用。
• 提高重用性。
• 提高安全性。封装原则:
• 将不需要对外提供的内容都隐藏起来。
• 把属性都隐藏,提供公共方法对其访问。
private(私有)关键字
- private关键字:
• 是一个权限修饰符。
• 用于修饰成员(成员变量和成员函数)
• 被私有化的成员只在本类中有效。 - 常用之一:
• 将成员变量私有化,对外提供对应的set ,get方法对其进行访问。提高对数据访问的安全性。
四、构造函数
- 特点:
- 函数名与类名相同
- 不用定义返回值类型
- 不可以写return语句
- 作用: 给对象进行初始化。
注意:
- 默认构造函数的特点:
- 参数列表为空,方法体为空,无参构造函数。
- 类中无显式写出任何构造函数,则默认是无参的构造函数。
- 若类中有 有参的构造函数 却没有显式的写出无参构造函数,则这个类是没有无参构造函数的
- 多个构造函数是以重载的形式存在的。
五、 this关键字
-
特点:this代表其所在函数所属对象的引用。
- 换言之:this代本类对象的引用。
每个实例化对象都有自己的this(保存该对象的引用地址)
-
什么时候使用this关键字呢?
- 当在函数内需要用到调用该函数的对象时,就用this。
this用法就两个:this. 和 this()
this只能使用在实例方法中。不能用在静态方法中。
this. 大部分可以省略,区分局部变量和实例变量的时候不能省略。
this() 只能出现在构造方法第一行,通过当前构造方法调用本类其它构造方法,代码复用。
六 、 static(静态)关键字
static关键字: 用于修饰成员(成员变量和成员函数)
- 被修饰后的成员具备以下特点:
- 随着类的加载而加载
- 优先于对象存在
- 被所有对象所共享
- 可以直接被类名调用
static修饰的都用“类名.”访问。(都不需要new对象,就能访问)
- 使用注意
- 静态方法只能访问静态成员
- 静态方法中不可以写this,super关键字
- 主函数是静态的
- static{} 是静态代码块,在类加载时执行,并执行一次。
- {} 实例语句块,在构造方法执行前执行,构造一次执行一次。
七、继承
1、一种联结类的层次模型
2、类继承:对象的一个新类从现有的类中派生
3、新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)
4、派生类可以从 基类郡 继承方法和实例变量
5、派生类可以修改或增加新的方法
6、所有类都有一个Object父类
- 特点:
1.Java 语言不支持多重继承
2.Java支持多层继承(继承体系)
3.子类只能继承父类的非私有(public 与 protected)成员变量与方法
4.当子类中定义的成员变量和父类中定义的成员变量同名时,子类中的成员变量会覆盖父类的成员变量,而不会继承。
5.当子类中的方法与父类中的方法 有相同的函数签名(相同的方法名,相同的参数个数与类型)时,子类方法覆盖父类的方法,而不会继承。
组合和继承的区别
组合 | 继承 | |
---|---|---|
共同点 | 面向对象中代码复用的方式 | 面向对象中代码复用的方式 |
类之间关系 | has-a 关系 | is-a 关系 |
实现方式 | 在新类里面 创建 原有类的对象,重复利用已有类的功能 | 面向对象的主要特性之一,允许根据其他类的实现来定义一个类的实现 |
类型与类型之间的关系
is a(继承) | has a(关联) | like a(实现) |
---|---|---|
Cat is a Animal(猫是一个动物),凡是能够满足is a的表示“继承关系”。A extends B | I has a Pen(我有一支笔)。凡是能够满足has a关系的表示“关联关系”。关联关系通常以“属性”的形式存在。 | Cooker like a FoodMenu(厨师像一个菜单一样).凡是能够满足like a关系的表示“实现关系”。实现关系通常是:类实现接口。A implements B |
使用继承的注意项
- 除非两个类之间是 is-a 关系,否则不要轻易使用继承, 过多地使用继承会破坏代码的可维护性。
- 不要仅仅为了实现多态而继承,如果类之间没有 is-a 的关系,可以通过实现接口与组合方式来达到相同的目的。
- 由于 Java 语言只支持单继承,如果 想同时继承两个类或多个类,在 Java 中是无法实现的。
- 在 Java 语言中,能使用组合就尽量不要使用继承。
八、多态
定义
1、允许不同类的 对象 对同一消息作出响应。
2、 当同一个操作作用在不同对象时,会有不同的语义,从而会产生不同的结果。
3、多态包括参数化多态和包含多态。
4、具有灵活、抽象、行为共享、代码共享 等优势。
5、解决应用程序函数同名问题。
- 体现:
父类或者接口的引用指向或者接收自己的子类对象。 - 作用:
多态的存在提高了程序的扩展性和后期可维护性 - 前提:
• 需要存在继承或者实现关系
• 要有覆盖操作
多态的特点
- 成员函数:
• 编译时:要查看引用变量所属的类中是否有所调用的成员。
• 在运行时:要查看对象所属的类中是否有所调用的成员。 - 成员变量:
• 只看引用变量所属的类(中的成员变量)。
一般多态体现语法:
父类(接口)类型 引用变量名 = new 子类(实现类)对象;
- 该引用变量只可以访问的是父类(接口)中存在的成员(成员方法、成员变量)
- 子类的覆盖行为对父类成员的访问影响如下:
2.1: 父类引用变量访问 成员方法 会从最底层找到实现了覆盖该方法的,子类的方法,从最后代找起,直到本身
2.2 : 父类引用变量访问 成员变量 只会是该父类中的 成员变量
多态的两种表现方式:
(1)方法的重载(overload) 和 方法的覆盖(overide) 定义
方法的重载(overload) | 方法的覆盖(overide) |
---|---|
编译时多态 | 运行时多态 |
方法多态性 | 方法动态绑定 |
同一个类中有多个同名的方法,它们或有不同的参数个数或有不同的参数类型。在编译时就可以确定调用哪个方法 | 子类可以覆盖父类的方法,实现类实现接口方法,并对其重写,以达到不同的作用,在运行时确定调用哪个方法 |
(2)动态绑定实现多态(方法覆盖的表现)
- 基类的引用变量不仅可以指向基类的实例对象,也可以指向其子类的实例对象。 抽象类、接口的引用变量也可以指向其实现类的实例对象。
- 程序调用的方法在运行期才动态绑定(绑定指的是将一个方法调用和一个方法主体连接到一起),就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。
(3)重载使用的注意
1)重载是通过方法不同的参数来区分的,例如不同的参数个数、不同的参数类型或不同的参数顺序。
2)不能通过方法的访问权限、返回值类型和抛出的异常类型来进行重载。
3)对于继承来说,如果基类方法的访问权限为 privae,那么就不能在派生类对其重载;如果派生类也定义了一个同名的函数,这只是一个新的方法,不会达到重载的效果。
(4)覆盖时需要注意以下几点:
1)派生类中的覆盖方法必须要和基类中被覆盖的方法有相同的函数名和参数。
2)派生类中的覆盖方法的返回值必须和基类中被覆盖的方法的返回值相同。
3)派生类中的覆盖方法所抛出的异常必须和基类(或是其子类)中被覆盖的方法所抛出的异常一致。
4)基类中被覆盖的方法不能为 private, 否则其子类只是定义了一个方法,并没有对其覆盖。
5)覆盖时,子类方法权限一定要 大于等于 父类方法权限
6)静态只能覆盖静态。
7)在子类覆盖方法中,继续使用被覆盖的方法,可以通过super.函数名获取。
(5)重载与覆盖的区别
重载 | 覆盖 |
---|---|
同一个类中方法之间的关系,是水平关系 | 子类和父类之间的关系,是垂直关系 |
多个方法之间的关系 | 只能由一个方法或只能由一对方法产生关系 |
参数列表不同 | 参数列表相同 |
根据调用时的实参表与形参表来选择方法体的 | 调用方法体是根据对象的类型(对象对应存储空间类型)来决定 |
九、super 关键字
- super和this的用法相同
- super的用法:super. 和 super()
- super不能出现在静态方法中,只能是 实例方法 。
- this代表 本类 应用
- super代表 父类 引用
- 当子父类出现同名成员时,可以用super进行区分
- super. 大部分可以省略,当父子都有相同的属性和方法时,在子类中访问父类的特征 时,必须使用 super.
- 子类要调用父类构造函数时,可以使用 super() 语句。
- 一个构造方法第一行什么也没有,自动会有一个super()
- super():是通过子类的构造方法 调用父类的构造方法。
- 一个构造方法第一行什么也没有,自动会有一个super()
十、子类的实例化过程
- 子类中所有的构造函数默认都会访问父类中空参数的构造函数
- 每一个构造函数的第一行都有一条默认的语句super(),调用父类的默认构造函数
- 子类会具备父类中的数据,所以要先明确父类是如何对这些数据初始化的
- 当父类中没有空参数的构造函数时,子类的构造函数必须通过this或者super语句指定要访问的构造函数
十一、final关键字
- final可以修饰类,方法,变量。
- final修饰的类不可以被继承。
- final修饰的方法不可以被覆盖。
- final修饰的变量是一个常量。只能被赋值一次。
- final修饰的引用一旦指向某个对象,则不能再重新指向其它对象,但该引用指向的对象内部的数据是可以修改的。
- final修饰的实例变量必须手动初始化,不能采用系统默认值。
- final修饰的实例变量一般和static联合使用,称为常量。
- 内部类只能访问被final修饰的局部变量。
十二、抽象类(abstract class)
(一) 抽象类概述
1. 抽象定义:
• 抽象就是从多个事物中将共性的,本质的内容抽取出来。
• 例如:狼和狗共性都是犬科,犬科就是抽象出来的概念。
2. 抽象类:
• Java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。
3. 抽象方法的由来:
• 多个对象都具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,并未抽取功能主体,那么只有功能声明,没有功能主体的方法称为抽象方法。
• 例如:狼和狗都有吼叫的方法,可是吼叫内容是不一样的。所以抽象出来的犬科虽然有吼叫功能,但是并不明确吼叫的细节。
(二)抽象类的特点
抽象类和抽象方法必须用abstract关键字来修饰。
抽象方法只有方法声明,没有方法体,定义在抽象类中。
• 格式:修饰符 abstract 返回值类型 函数名(参数列表);抽象类不可以被实例化,也就是不可以用new创建对象。原因如下:
• 抽象类是具体事物抽取出来的,本身是不具体的,没有对应的实例。例如:犬科是一个抽象的概念,真正存在的是狼和狗。
• 而且抽象类即使创建了对象,调用抽象方法也没有意义。抽象类通过其子类实例化,而子类需要覆盖掉抽象类中所有的抽象方法后才可以创建对象,否则该子类也是抽象类。
(三)抽象类注意点
- 抽象类也有构造函数。抽象类被继承,在子类的构造函数中会调用父类的构造函数,父类(抽象类)提供构造函数来给子类调用super(),如果没有提供的话就会调用默认的构造函数。
- abstract关键字不能与哪些关键字共存? static、final、private
- 抽象类中可以没有抽象方法,但有抽象方法的一定是抽象类
(四)抽象类面试题
判断:java语言中凡是没有方法体的方法都是抽象方法。
- 不对,错误的。
Object类中就有很多方法都没有方法体,都是以“;”结尾的,但他们都不是抽象方法 - 例如:
public native int hashCode();
这个方法底层调用了C++写的动态链接库程序。
前面修饰符列表中没有:abstract。有一个native。表示调用JVM本地程序。
十三、接口(interface)
(一)定义
- 格式:
interface 接口名 {} - 接口中的成员修饰符是固定的。
•成员常量:public static final
•成员函数:public abstract - 接口的出现将“多继承”通过另一种形式体现出来,即“多实现”。
(二)接口的特点
- 接口是对外暴露的规则。
- 接口是程序的功能扩展。
- 接口可以用来多实现。
- 类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。
- 接口与接口之间可以有继承关系。
(三)抽象类和接口在语法上的区别
接口一般都是对“行为”的抽象。
抽象类 | 接口 |
---|---|
抽象类是半抽象的。 | 接口是完全抽象的。 |
抽象类中有构造方法。 | 接口中没有构造方法。 |
类和类之间只能单继承。 | 接口和接口之间支持多继承。 |
一个抽象类只能继承一个类(单继承)。 | 一个类可以同时实现多个接口。 |
抽象类中可以有非抽象方法 | 接口中只允许出现常量和抽象方法。 |
(四)接口与解耦合
- 面向接口编程,可以降低程序的耦合度,提高程序的扩展力。符合OCP开发原则。
- 接口的使用离不开多态机制。(接口+多态才可以达到降低耦合度。)
接口可以解耦合,解开的是谁和谁的耦合
1. 任何一个接口都有调用者和实现者。
2. 接口可以将调用者和实现者解耦合。
3. 调用者面向接口调用。
4. 实现者面向接口编写实现。
- 大项目的开发,一般都是将项目分离成一个模块一个模块的
- 模块和模块之间采用接口衔接。降低耦合度。
十四、内部类
定义
- 将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)。
访问特点
- 内部类可以直接访问外部类中的成员,包括私有成员。
- 而外部类要访问内部类中的成员必须要建立内部类的对象。
内部类的位置
- 内部类定义在成员位置上
• 可以被private static成员修饰符修饰。
• 被static修饰的内部类只能访问外部类中的静态成员。 - 内部类定义在局部位置上
• 也可以直接访问外部类中的成员。
• 同时可以访问所在局部中的局部变量,但必须是被 final 修饰的。
匿名内部类
- 就是内部类的简化写法。
- 前提:
• 内部类可以继承或实现一个外部类或者接口。 - 格式为:
• new 外部类名或者接口名 () {覆盖类或者接口中的代码,(也可以自定义内容。)} - 简单理解:
• 就是建立一个建立一个带内容的外部类或者接口的子类匿名对象。
十五、异常
(1)异常的体系
Throwable | |
---|---|
Error | 通常出现重大问题如:运行的类不存在或者内存溢出等。不编写针对代码对其处理 |
Exception | 在运行时出现的一些情况,可以通过try catch finally捕获 |
- Exception和Error的子类名都是以父类名作为后缀
(2)Throwable中的方法
方法名 | 作用 |
---|---|
getMessage() | 获取异常信息,返回字符串 |
toString() | 获取异常类名和异常信息,返回字符串 |
printStackTrace() | 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void |
printStackTrace(PrintStream s) | 通常用该方法将异常内容保存在日志文件中,以便查阅 |
(3)throws和throw
throws | throw |
---|---|
用于标识函数暴露出的异常 | 用于抛出异常对象 |
用在函数上,后面跟异常类名 | 用在函数内,后面跟异常对象 |
(4)异常处理
try
{
//需要检测的代码;
}
catch(异常类 变量)
{
//异常处理代码;
}
finally
{
//一定会执行的代码;
}
Finally代码块只有一种情况不会被执行。就是在之前执行了System.exit(0)。
(5)自定义异常
- 自定义类继承Exception或者其子类。
- 通过构造函数定义异常信息。
Class DemoException extends Exception
{
DemoException(String message)
{
super(message);
}
}
- 通过throw将自定义异常抛出。
(6)异常细节
- RuntimeException以及其子类如果在函数中被throw抛出,可以不用在函数上声明。
- 一个方法被覆盖时,覆盖它的方法必须抛出相同的异常或异常的子类。
- 如果父类抛出多个异常,那么重写(覆盖)方法必须抛出那些异常的一个子集,不能抛出新的异常。
十六、包
- 对类文件进行分类管理。
- 给类提供多层命名空间。
- 写在程序文件的第一行。
- 类名的全称的是 包名.类名。
- 包也是一种封装形式。
classpath
- 给JVM提供的一个环境变量。
- 指定类或者包所在的路径。
包之间的访问
- 被访问的包中的类权限必须是public的。
- 类中的成员权限:public或者protected
- protected是为其他包中的子类提供的一种权限
四种权限
范围从大到小排序:public > protected > 默认 > private
public | protected | default | private | |
---|---|---|---|---|
1. 范围 | · | · | · | · |
同一个类中 | √ | √ | √ | √ |
同一个包中 | √ | √ | √ | |
子类 | √ | √ | ||
不同包中 | √ | |||
2. 修饰的对象 | · | · | · | · |
属性 | √ | √ | √ | √ |
方法 | √ | √ | √ | √ |
类 | √ | √ | ||
接口 | √ | √ |
import
- 简化类名。
- 一个程序文件中只有一个package,可以有多个import。
- 用来导包中的类,不导入包中的包。
java.lang.* ;这个包下的 类 不需要使用import导入
易错点:import java.*; 这是不允许的,因为在java语言中规定,这里的 * 只代表某些类的名字。
Jar包
- Java的压缩包
• 方便项目的携带。
• 方便于使用,只要在classpath设置jar路径即可。
• 数据库驱动,SSM框架等都是以jar包体现的。
Jar包的操作
通过jar.exe工具对jar的操作:DOS命令
- 创建jar包
• jar -cvf mypack.jar packa packb - 查看jar包
• jar -tvf mypack.jar [>定向文件] - 解压缩
• jar -xvf mypack.jar - 自定义jar包的清单文件
• jar –cvfm mypack.jar mf.txt packa packb
十七、
- 很喜欢老师的比喻
杜老师:程序员是计算机和现实世界的一座桥梁
毕老师:在面对对象的思想中,程序员是指挥者
- 不知这么理解面对对象是否有正确性:
- 程序员(角色:桥)负责把现实世界的一个个对象抽象出他们的属性和行为,并把这些对象特征转化为计算机认识的代码-->类与接口,并在类与接口中实现现实对象的属实和行为(成员变量、成员方法)。
- 当程序员(角色:指挥者)编写程序,需要程序做某一件事、实现某个功能时,我们只要找到能完成这些事情的对象们(怎么找?new!),指挥他们去做就行,至于对象们是怎么实现这个功能的,指挥者是不用知道的,我们只要得到最后的正确结果。