面向对象的编程
基本概念:对象、类、属性和方法
对象是状态和行为的集合
状态:说明对象中包含的数据。在Java中,这些是对象的字段
行为:对象支持的操作,在Java中,这些被称为方法,方法只是OO为函数说话,调用方法=调用函数
类
每个对象都有一个类,类定义了类型和实现:
一个类定义了方法和字段
方法和字段统称为成员
包括类成员变量和类方法
静态/实例成员变量(方法)
类变量:与类相关而不是与类实例相关的变量。可以将方法与一个类——类方法关联起来。
那些不是类方法或类变量的方法和变量被称为实例方法和实例变量。
引用类实例中的方法和变量来使用实例方法/变量。
类变量和类方法与类关联并发生在一个类中。使用它们不需要创建对象。实例方法和变量在类的每个实例中出现一次。
静态方法无法直接调用非静态成员,而实例方法(没有静态关键字的声明)必须在特定对象上调用。
接口和枚举
Interface和Class: 定义和实现ADT
接口中只有方法的定义,没有实现
接口之间可以继承与扩展
一个类可以实现多个接口(从而具备了多个接口中的方法)
一个接口可以有多种实现类
Java接口和类
接口:确定ADT规约;类:实现ADT
也可以不需要接口直接使用类作为ADT,既有ADT定义也有ADT实现
实际中更倾向于使用接口来定义变量
在接口中使用默认方法
接口中的每个 方法在所有类中都要实现,缺点是会导致部分方法的重复实现
通过default方法,在接口 中统一实现某些功能,无需在各个类中重复实现它。
default 方法的典 型使用方式:以增量式的为接口增加额外的功能而不破坏已实现的类
封装和隐藏信息
区分一个设计良好的模块和一个糟糕的模块的一个最重要的因素是它对其他模块隐藏内部数据和其他实现细节的程度
精心设计的代码隐藏了所有实现细节:将API与实现完全分离;模块仅通过API进行通信
他们对彼此的内部运作视而不见,这被称为信息隐藏或封装,这是软件设计的一个基本原则。
信息隐藏的好处
1.解耦组成系统的类:允许它们单独开发、测试、优化、使用、理解和修改
2.加快系统开发:类可以并行开发
3.减轻维护负担:类可以更快地被理解和调试,而不用担心会损害其他模块
4.实现有效的性能调整:“热门”类可以单独进行优化
5.增加软件重用:松散耦合类在其他情况下通常很有用
接口隐藏的信息:
1.使用接口类型声明变量
2.客户端仅使用接口中定义的方法
3.客户端代码无法直接访问属性
成员修饰符
private:仅当前类
default:当前类及同一包内
protected:当前类、同一包内以及子孙类
public:当前类、同一包内、子孙类及其他包
继承和重写
重写:
可重写的方法:一种允许重新实现的方法。
在Java中,默认情况下是可重写的,即没有特殊的关键字。
严格继承:子类只能添加新方法,无法重写超类中的方法
方法重写是一种语言特性,它允许子类或子类提供方法的特定实现,该方法已经由其超类或父类提供。
重写的函数有着相同的签名
子类只能向超类添加新的方法,它不能覆盖它们
如果一个方法不能在Java程序中被覆盖,它必须以关键字final作为前缀。
所执行的方法的版本将由用于调用它的对象决定。
父类型中的被重写函数体不为空:意味着对其大多数子类型来说,该方法是可以被直接复用的。
对某些子类型来说,有特殊性,故重写父类型中的函数,实现自己的特殊要求
如果父类型中的某个函数实现体为空, 意味着其所有子类型都需要这个功能, 但各有差异,没有共性,在每个子类中均需要重写。
如果使用父类的对象来调用该方法,则将执行父类中的版本;如果使用子类的对象来调用该方法,则将执行子类中的版本。
当一个子类包含一个覆盖超类的方法的方法时,它还可以通过使用关键字super来调用超类方法。
注意:重写的时候,不要改变原方法的本意
final
final字段:防止在初始化后重新分配到字段
final方法:防止覆盖方法
final类:防止扩展类
抽象类
只有定义没有实现
抽象类不能实例化(不能用new 生成对象)
继承某个抽象类的子类在实例化时,所有父类中的抽象方法必须已经实现
多态、子类型、重载
特殊多态:一个方法可以有多个同名的实现
参数化多态:一个类型名字可以代表多个类型(泛型编程)
子类型多态、包含多态:.一个变量名字可以代表多个类的实例(子类型)
特殊多态与重载
重载:多个方法具有同样的名字,但有不同的参数列表或返回值类型
价值:方便 client 调用, client 可用不同的参数列表,调用同样的函数
函数重载是一个静态多态。
函数根据参数列表进行解析,根据参数列表进行最佳匹配
静态类型检查,对象类型作为参数时取决于引用类型
在编译阶段时决定要具体执行哪个方法 (static type checking)重写的方法则是在运行时进行动态检查
重载的规则
参数多态性与泛型编程
参数多态性是指方法针对多种类型时具有同样的行为,此时可使用统一的类型变量表达多种类型
泛型:在运行时根据指定类型确定具体类型(编译成class文件时,会用指定类型替换类型变量“擦除”)
泛型编程是一种编程风格,其中数据类型和函数是根据待指定的类型编写的,随后在需要时根据参数提供的特定类型进行实例化。
泛型编程围绕“从具体进行抽象”的思想,将采用不同数据表示的 算法进行抽象,得到泛型化的算法,可以得到复用性、通用性更强 的软件。
使用**菱形操作符<>**来帮助声明类型变量。
使用泛型变量的三种形式:泛型类、泛型接口和泛型方法
泛型类:类中如果声明了一个或多个泛型变量,则为泛型类
这些类型变量称为类的类型参数
泛型接口:接口中声明一个或多个泛型变量
泛型方法:一个方法声明了一个或多个类型变量
-这些类型变量被称为方法的形式类型参数。
-形式类型参数列表的形式与类或接口的类型参数列表相同。
子类型多态:
一个类只有一个父类,但可以实现多个接口
B是A的一个子类型,意思是,每个B都是A,每个B都满足A的Spec。
子类型的规约不能弱化超类型的规约
子类型多态:不同类型的对象可以统一的处理而无需区分
在Java中一些重要的对象方法
设计好的类
不可变类的优点
1.简单
2.固有线程安全
3.可以自由共享
4.无需防御副本
5.优秀的构建块
如何编写不可变类
1.不提供任何突变
2.确保不可重写任何方法
3.使所有字段成为最终字段
4.将所有字段设为私有字段
5.确保任何可变组件的安全性(避免重复暴露)
6.实现toString()、hashCode()、clone()、equals()等。
OOP的历史