基本数据类型、对象数据类型
Boxed Primitives:Integer Double Boolean …… 通常在集合类型中使用,一般可以自动转换
静态类型检查、动态类型检查
java 是一门静态检查语言,
静态类型检查就是在编译时进行类型检查,
动态类型检查是在运行时进行类型检查。
Mutable/Immutable
一个是可变类型,一个是不可变类型。总之,几个重点,
引用类型可以是不可变类型,也就是在确认其指向的空间后,不可再改变这个指针。
可变类型性能较好,可为了安全通常要用到防御性拷贝,没不可变类型方便。
一个可变类型不应该有多个别名,这样能避免很多错误。
Snapshot
Collections.unmodifiableType 可以生成一个无法改变的集合类型
做题时的错误,
String s = null;
System.out.println(s.length());
在运行时会报NullPointer错误。
String不会自动被两个变量引用,会直接分配新内存。
原来迭代器中有一个元素,迭代器指针在这个元素之后,这时,删除这个元素,得到Iterator.hasnext = true;
Specification、前置/后置条件
前置条件越弱,后置条件越强,规约的强度越强。
也有不可比的情况
ADT操作的四种类型
首先ADT由操作定义与内部如何实现无关。
表示独立性
表示独立性:client使用ADT时无需考虑其内部如何实现,ADT内部表现的变化不应该影响外部spec和客户端。
Representation exposure 表示泄漏
client不应直接接触类成员变量。
表示泄漏影响表示不变量,也影响表示独立性:
无法在不影响客户端的情况下改变其内部表示。
避免方法:private、final、defensive copy
Invariants 不变量 & Representation Invariant 表示不变量
ADT应保持其不变量在任何时候总是true;
ADT负责其不变量,与client的任何行为无关。
作用:保持程序的"正确性",容易发现错误。
Abstraction Function 抽象函数
表示空间R | 抽象空间A |
值的实际实现本质 | 抽象表示(client看到和使用的值) |
ADT实现者关注表示空间R | 用户关注抽象空间A |
设计ADT:(1) 选择R和A;(2) RI --- 合法的表示值; (3) 如何解释合法的表示值 ---映射AF
R到A的映射
一定是满射:A中元素总有R中具体的实现
未必是单射:A中一个元素在R中可能有多重实现方式
未必是双射:R中表示不符合A中需求(如图中"abbc")
抽象函数AF:R和A之间映射关系的函数
AF:R->A
做出具体的解释:每个rep value如何映射到abstract value
对于RI :R-> Boolean
RI:某个具体的"表示"是否合法;表示值的一个子集,包含所有合法的表示值;一个条件,描述了什么是"合法"表示值。
Safety from Rep Exposure
证明代码并未对外泄露其内部表示
保证不变量为true,不变量:
-
通过creators和producers创建
-
受mutators和observers保护
-
无表示泄漏发生
错题:测试相关不用展示给客户端。
Overriding
重写后最好super()对运行一次父类
在运行阶段决定
Overloading
重载:多个方法具有同样的名字,但有不同的参数列表或返回值类型
Overload只能通过不同的参数列表进行重载,跟抛出的异常无关。
在编译阶段决定
多态性
一个超类的多态性体现在,如果这个拿他的一个子类来对一个超类实例赋值,且子类有重写的超类方法,则在调用这个超类方法时会优先运行子类的重写后的方法。也就是runtime中dynamic checking的礼物。
错题: interface中可以有public static final的域,也可以有static方法
overload不能把返回值变没了