CHAPTER 1-8 易错点整理
1 软件构造八大视图间的转化关系
2 可变类型/不可变类型
Java调用可变类型/不可变类型的过程均为按引用调用,但可以视为C语言的按引用调用/按值调用。
一个可变对象的引用,经多轮传递,很难跟踪错误。需采用防御式拷贝,即new一个同类型实例用于传参,该步骤由调用者/被调用者执行均可。
不可变类型的优势在于安全,无需采用防御式拷贝。类似于CPU对于共享内存的写时复制策略,可通过内存共享相同的值,降低复制带来的内存浪费。但遇到频繁修改的情况,将产生大量临时拷贝,需要垃圾回收。
可变类型的优势在于更好的性能,以及多个模块间数据共享。只有一个引用(无别名)时,可变类型是安全的。
编写良好的代码应根据需求,折中选取合适的类型。
3 可变引用/不可变引用
上述讨论的是变量的可变/不可变。对于引用的可变/不可变,Java提供了保留字final用于手动规定引用的可变性。
引用与变量值的可变性并不相关
4 关系快照
程序运行中的内部状态。
5 复杂数据类型
List/Set/Map在添加items的时候会做静态类型检查。
注意迭代器Iterator在声明的时候要声明类型。
避免报错:Type mismatch: cannot convert from Object to MultiEntry<L>
示例:MyIterator:尽可能多用final
snapshot diagram of myiterator
6 删除List元素
1 for迭代循环 + list.remove():首次成功,第二次抛异常。
2 索引循环 + list.remove():删不干净。
3 迭代器循环 + list.remove():同(2)。
4 迭代器循环 + iterator.remove():正解!
7 基本数据类型及其包装类都是Immutable
8 获取可变集合的不可修改视图:
Collections.unmodifiableList(list)
Collections.unmodifiableSet(set)
Collections.unmodifiableMap(map)
9 文档
1 类层次结构,直接子类,接口的列表以及对它们的描述;
2 构造函数摘要,方法摘要;每个方法和构造函数的详细描述;
3 方法签名,参数,返回值。
10 链接
1 静态链接(build time):当连接工具认为一个功能被调用的时候,他就把需要的文件从库中复制粘贴到相应程序中。
2 动态链接(run time):不去复制粘贴,只是给一个标志,在运行时会加载到内存中。
11 防御式拷贝
通过防御式拷贝,给客户端返回一个全新的对象;大部分时候该拷贝不会被客户端修改,可能造成大量的内存浪费;如果使用不可变类型,则节省了频繁复制的代价。安全的使用可变类型:局部变量,不会涉及共享;只有一个引用。
12 前置/后置条件
代码中蕴含的“设计决策”:给编译器读注释形式的“设计决策”:给自己和别人读
没规约,没法写程序;即使写出来,也不知道对错;程序与客户端之间达成的一致;
Spec给“供需双方”都确定了责任,在调用的时候双方都要遵守
只讲“能做什么”,不讲“怎么实现”
前置条件:对客户端的约束,在使用方法时必须满足的条件
后置条件:对开发者的约束,方法结束时必须满足的条件
契约:如果前置条件满足了,后置条件必须满足
前置条件不满足,则方法可做任何事情。
除非在后置条件里声明过,否则方法内部不应该改变输入参数
13 规约
14 ADT操作类型
可变类型的对象:提供了可改变其内部数据的值的操作
不变数据类型: 其操作不改变内部值,而是构造新的对象
Creators:构造器、Producers:生产器、Observers:观察器、Mutators:变值器
15 多态
多态的三种形式:特殊多态(功能重载)、参数化多态、子类型多态。
特殊多态:工作在不同的类型之间,函数行为可能不一样