第三章总结
关于ADT和OOP
3.1 数据类型
改变变量和改变值:immutable不能改变值
immutable引用:final
(final类不能被继承,final方法不能被重写)
mu:StringBuilder, Date
immu:String,所有原始类型,Biginteger, Bigdecimal
不要使用Date
当仅有一个引用时,二者的使用区别不大;当有多个引用时,二者的区别很大。
mu优点:共享;缺点:传递、return时易出错,且需要防御性拷贝(创造一个同原来值相同的新对象)。
基本类型和对象类型:
区分方法:开头的大小写
基本类型都是immutable,分配在栈上
对象类型mu/immu都有,分配在堆上,垃圾回收
基本类型的包装类:是对象类型,java自动打包拆包(效率低)
静态类型和动态类型:
静态方法只有通过实例调用动态方法/访问动态变量。
成员变量/实例变量属于对象,在堆内存中;静态变量属于类,在全局区中(还有全局变量)。
动态检查和动态检查:
static:使用错误类型,syntax errors
dynamic:非法参数,超出范围索引,调用null,syntax
errors
静态检查只针对类型,与变量的值无关;动态检查针对由特定值引起的错误。
注意int division/overflow和float特殊值。
snapshot diagram:
栈和堆的瞬时状态。
复杂数据类型-数组和Collecion:
Array-List:后者只能存储对象类型,长度可变
Arrays.asList(new String[] { “a”, “b”,
“c” });
Set:无序
Map:键值对,
当添加一个item时,编译器会静态检查。
这些都是接口,可在不同情况下选择不同的实现(ArrayList/LinkedList, HashSet, HashMap)
Iterator/迭代器:
ConcurrentModificationException-破坏迭代器(迭代过程中修改list/set/map)
一些wrappers:unmodifiable+List/Map/Set
public static Set unmodifiableSet(Set<?
extends T> s);
null
null只能赋给对象类型。
非空的collection可以包含null值。
3.2 spec书写
1.方法/method
@param
@return
2.规格说明/specification
变量-类型+(final)
行为等价:
行为等价和观察等价:针对对象,observer观察一样则观察等价,mutator操作以后一样则行为等价。
(immu类型没有mutator方法,所以二者是一个东西,或者说没有行为等价)。
前置条件/requires:param
后置条件/effects:return, throws
Exceptional behavior: what it does if precondition violated
如果前置条件满足了,则后置条件必须满足;反之后置条件无需满足
编译器完成pre/post条件中对类型的检查
3.设计规格说明
只能有单个返回值。
确定的spec:对任意满足pre的输入的输出是唯一/确定
欠定的spec:允许同一输入存在多个有效输出/输出结果不确定
(一个欠定的spec通常是通过完全确定性的实现来实现的)
spec的强度:前置条件松,后置严,则spec更强(但也存在无法比较的两个spec)。
“要求的少,承诺的多。”
3.3 ADT
creators: create对象,通常是constructor/static方法(工厂方法)
producers: 从已有对象产生新对象
observers: 观察
mutators: 改变
immu类型没有mutator。
representation independence
测试一个ADT:
(书写测试用例和测试策略)
RI=rep invariant
AF=abstract function
R:实现时用到的值空间
A:需要支持的值空间
AF:R->A是满射的,但未必单射,未必双射。
RI:R->boolean:For a rep value r , RI® is true if and
only if r is mapped by AF
RI形成R的一个子集(其中元素都被AF映射到了A中)
用断言检查不变性/checkRep,在所有creator和mutator最末调用。
抽象值永远不可改变,表示值可以改变
safety from rep exposure:保证不泄露内部表示的策略
注意:
在初始化时使invariant为真;所有修改都使不变性得到保持;creator, producer为新对象建立不变性,observer, mutator保持不变性。
3.4 OOP
区分静态方法和实例方法,静态属性和动态属性
静态方法无法调用非静态成员(方法和变量)
一个接口可以扩展其他接口;
一个类可以实现多个接口(但不能继承多个类)
接口中每个抽象方法必须有对应的实现
一般来说创建一个HashSet的对象后把上溯到了Set, HashSet有但是Set没有的属性和方法就不能再用了,但提高了可复用性(面向接口编程)
接口不能有构造方法,但可以有static方法
(可以通过接口进行信息隐藏)
继承和重写:
【调用父类的构造方法时,必须是构造方法的第一行
子类不能有(签名)新的构造方法
区分抽象类和接口(可以说接口是特殊的抽象类)