- 类定义了对象拥有哪些属性(成员变量)和操作(成员函数/方法)
- 对象是按照类的定义制造出的实体
- 一个类可以创建很多个对象,每个对象有自己数据
- 面向对象程序设计的第一步,就是在问题领域(issue)中识别出有效对象,然后从识别出的对象中抽取出类来
- 一个对象可以由其他类的对象来组成,而类定义了这样的组合关系
- 对象和对象之间的联系紧密程度叫做耦合。对象和对象的耦合程度越紧,表现在源代码上就是他们的代码是互相依赖、互相牵制的。我们理想的模型,是对象和对象之间的耦合要尽可能松,平行的对象要尽量减少直接联系,让更高层次的对象来提供通信服务
- 封装,就是把数据和对这些数据的操作放在一起,并且用这些操作把数据掩盖起来,是面向对象的基本概念之一,也是最核心的概念
- static修饰的变量和函数被称为类变量和类函数
- 基于已有的设计创造新的设计,就是面向对象程序设计中的继承。在继承中,新的类不是凭空产生的,而是基于一个已经存在的类而定义出来。通过继承,新的类自动获得基础类中所有的成员(除构造方法),包括成员变量和方法,包括各种访问属性的成员,无论是public还是private
- 我们把用做基础派生其他类的那个类叫做父类、超类或基类,而派生出来的新类叫做子类
- 继承表达了一种is-a的关系,即子类的对象可以被看作是父类的对象
- 所有的对象变量都是多态的,多态就是指一个变量可以保存许多形态的对象,即声明的类型(静态类型,即编译时)或声明类型的任何子类型(动态类型,即运行时)的对象
- Java(大部门OOP语言,除了C++)中的变量赋值操作,是让两个对象的管理者去管理一个共同的对象,不存在对象对对象的赋值,赋值运算符就是让这个变量去指向了另一个对象,原对象并没有消失。在这个过程中就可能存在向上造型(基本类型叫类型转换,对象类型叫做造型)。
String str1 = "str1"; String str2 = "str1"; str1 = str2;
- 对象变量调用函数的时候,调用哪个函数被称作函数的绑定
- 静态(编译)绑定/早绑定:根据变量的声明类型来决定
- 动态(运行)绑定/晚绑定:根据变量的动态类型来决定
-
Java中默认都是动态绑定
-
- 成员函数中调用其他成员函数也是通过this这个对象变量来实现动态绑定
- Java通过Object类实现单根结构,所有的类都继承了Object类
- Object中的equals是判断两个管理者管理的是不是同一个对象
- 消除代码复制,抽取公共方法
- 通过封装提高聚合,降低耦合
- 通过设计模式提高可拓展性
- 两种抽象
- 与具体相对:表示一种概念而非实体
- 与细节相对:表示在一定程度上忽略细节而着眼大局
- 代码阅读方法
- 从主函数开始
- 从高层次到低层次
- 数据与表现分离
- 责任驱动设计
- 通过监听器实现反转控制/注入控制
- 内部类
- 定义在类或函数内部的类
- 内部类能够访问外部的全部资源
- 包括任何私有成员
- 外部是函数时,访问的变量必须是final的
- MVC设计模式
- M = Model
- 保存和维护数据,提供接口让外部修改数据,通知表现需要刷新
- V = View
- 从模型获得数据,根据数据画出表现
- C = Control
- 从用户得到输入,根据输入调整数据
- M = Model
- 异常捕获机制流程
Loading
flowchart LR classDef decisionNode fill:#f8d7da,stroke:#d73a4a,shape:diamond classDef processNode fill:#b5e8f4,stroke:#1f76c4,shape:rect START([开始]) END([结束]) S0[有异常抛出]:::processNode S1[返回给调用者]:::processNode S2[退出到外层作用域]:::processNode S3[执行catch块]:::processNode S4[继续执行后续代码]:::processNode J1{是否在try块中}:::decisionNode J2{catch是否匹配}:::decisionNode J3{是否在函数作用域内}:::decisionNode START --> S0 S0 --> J1 J1 --> |Y| J2 J2 --> |Y| S3 S3 --> S4 S4 --> END J1 --> |N| J3 J3 --> |Y| S1 S1 -.-> |递归检查| J1 J3 --> |N| S2 J2 --> |N| S2 S2 -.-> |递归检查| J1 - 异常机制的最大好处:清晰地分开了正常的业务逻辑代码和遇到情况时的处理代码
- 异常遇到继承
- 当覆盖一个函数时,子类的函数不能声明抛出比父类更多层次更高的异常类型
因为对象调用会优先调用子类的函数
- 子类的构造函数,必须声明父类可能抛出的全部异常
因为子类对象在构造时会先调用父类的构造函数
- 当覆盖一个函数时,子类的函数不能声明抛出比父类更多层次更高的异常类型
- 流
- 单向的( stream 翻译为小溪)
- 流要么是输入流,要么是输出流
- 二进制数据
- 采用InputStream/OutputStream
- 基于字节来操作流
- 采用InputStream/OutputStream
- 过滤器流
- 使用过滤器流的叠加可以支持更复杂的流操作,而不仅仅是字节
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("demo.dat"))); out.write(123456); // 直接输出int到文件中 out.close();
- 使用过滤器流的叠加可以支持更复杂的流操作,而不仅仅是字节
- 文本数据
- 采用Reader/Writer
- 基于Unicode来操作流
- 实际很少有Unicode编码的文件,通常都是国标码或者Unicode(UTF-8)或其他编码,所以通常需要通过过滤器流叠加Stream二进制流来操作
- 在读取到二进制文件后,会通过二进制流外层的流自动从Unicode转换为当前系统编码,但通常会进行手动指定,防止乱码
- 采用Reader/Writer
- 流的应用
- Socket
- 通过nc -l 端口号模拟建立Socket
- Socket
- 对象串行化
- Serializable接口
