HIT 软件构造 5 :第4,5章复习

目录

一、数据类型与类型检验

1. 基本数据类型、对象数据类型(4.1)

2. 静态类型检查、动态类型检查(4.2)

(1)静态类型检查

(2)动态类型检查

(3)静态与动态检查比较

3. Mutable/Immutable(4.3)

(1)Immutable

(2)Mutable

4. 值的改变、引用的改变(4.3)

5. 防御式拷贝(4.3)

6. Snapshot diagram(4.4)

(1)Snapshot diagram中的基本类型与对象类型的值

(2)重新赋值和不可变值

(3)可变值

(4)不可变引用

二、设计规约

1. Specification、前置/后置条件

(1)Specification(5.2.2)

(2)前置/后置条件(5.2.4)

2. 行为等价性(5.2.3)

3. 规约的强度


4-5章考点如下:

HIT 软件构造 5 :第4,5章复习

一、数据类型与类型检验

1. 基本数据类型、对象数据类型(4.1)

数据类型(Types):一组值,以及可以对这些值执行的操作。示例:boolean、int、double、String

变量(Variables):用特定数据类型定义,可存储满足类型约束的值

基本数据类型(primitive types):int,long,boolean,double,char

对象数据类型(object types ):String,BigInteger

基本类型是小写的,而对象类型是以大写字母开头的。

HIT 软件构造 5 :第4,5章复习

2. 静态类型检查、动态类型检查(4.2)

静态类型语言:在编译阶段进行类型检查,如Java

动态类型语言:在运行阶段进行类型检查,如Python

三种自动检查:

1. 静态类型检查:在程序运行之前自动发现错误。

2. 动态类型检查:执行代码时自动发现错误。

3. 无检查:语言根本不能帮助您找到错误。会得到错误的答案。

静态类型检查 >> 动态 >> 无检查

(1)静态类型检查

静态类型检查:可在编译阶段发现错误,避免了将错误带入到运行阶段,可提高程序正确性/健壮性。

包括:

1. 语法错误(Syntax errors): 比如额外的标点符号或者虚假的单词。甚至像Python这样的动态类型语言也会进行这种静态检查。

2. 类名/函数名错误(Wrong names): 例如 Math.sine(2) . (正确为 sin)

3. 参数数目错误(Wrong number of arguments): 例如 Math.sin(30, 20) .

4. 参数类型错误(Wrong argument types):例如 Math.sin("30") .

5. 返回值类型错误(Wrong return types): 例如一个函数声明返回int ,却 return "30"; .

(2)动态类型检查

包括:

1. 非法的参数值(Illegal argument values):例如,整数表达式x/y只有在y实际为零时才是错误的;否则就行了。所以在这个表达式中,被零除不是静态误差,而是动态误差。

2. 非法的返回值(Unrepresentable return values): 例如,当特定的返回值不能在类型中表示时。要求boolean,返回int。

3. 越界(Out-of-range indexes): 例如,在字符串上使用负数或太大的索引。

4. 对空对象引用调用方法。如空指针。

(3)静态与动态检查比较

静态检查往往是关于类型,即与变量的特定值无关的错误。静态类型保证变量将具有该集合中的某个值,但直到运行时我们才确切知道它具有哪个值。因此,如果错误仅由某些值引起,如被零除或索引超出范围,则编译器不会对此引发静态错误。

相比之下,动态检查往往是由特定值引起的错误。

3. Mutable/Immutable(4.3)

(1)Immutable

不变数据类型(Immutable types):一旦被创建,其值不能改变

Java还为我们提供了不可变的引用:只分配一次而从不重新分配的变量。如果是引用类型,也可以是不变的:一旦确定其指向的对象,不能再被改变要使引用不可变,使用关键字final声明它

final int n = 5;

final Person a = new Person(“Ross”)

如果编译器无法确定final变量不会改变,就提示错误,这也是静态类型检查的一部分。

所以,尽量使用final变量作为方法的输入参数、作为局部变量。

final性质:

1. final类无法派生子类  2. final变量无法改变值/引用 3. final方法无法被子类重写

(2)Mutable

不变对象:一旦被创建,始终指向同一个值/引用,例如String

可变对象:拥有方法可以修改自己的值/引用,例如StringBuilder

在多个引用对象时出现差异

HIT 软件构造 5 :第4,5章复习

1. 可变数据类型的优势

使用不可变类型,对其频繁修改会产生大量的临时拷贝(需要垃圾回收)。可变类型最 少化拷贝以提高效率。

HIT 软件构造 5 :第4,5章复习

使用可变数据类型,可获得更好的性能。也适合于在多个模块之间共享数据。

2. 可变数据类型的劣势

不可变类型更“安全”, 在其他质量指标上表现更好。

可变数据类型容易使函数超出了spec范畴,因为它改变了输入参数的。这种错误非常难于跟踪和发现。对其他程序员来说,也难以理解。

4. 值的改变、引用的改变(4.3)

赋值:使用“=”为变量赋值。

String foo;

foo = “IAP 6.092”;

赋值可以与变量声明结合使用。

double badPi = 3.14;

boolean isJanuary = true;

改变一个变量:将该变量指向另一个值的存储空间。

改变一个变量的值:将该变量当前指向的值的存储空间中写入一个新的值。

5. 防御式拷贝(4.3)

防御式拷贝:返回对象的新副本,例如给客户端返回一个全新的Date对象

不可变类型永远不需要防御式拷贝。

大部分时候该拷贝不会被客户端修改, 可能造成大量的内存浪费。如果使用不可变类型, 则节省了频繁复制的代价。

安全的使用可变类型:局部变量,不会涉及共享;只有一个引用。如果有多个引用(别名),使用可变类型就非常不安全。

6. Snapshot diagram(4.4)

Snapshot diagram:用于描述程序运行时的内部状态

用处:1. 便于程序员之间的交流 2. 便于刻画各类变量随时间变化 3. 便于解释设计思路

(1)Snapshot diagram中的基本类型与对象类型的值

基本类型的值:

–基本类型的值由裸常量表示。传入箭头是对变量或对象字段中的值的引用。

HIT 软件构造 5 :第4,5章复习

对象类型的值:

–对象值是按其类型标记的圆。

–当我们想显示更多细节时,我们会在里面写上字段名,箭头指向它们的值。更详细地说,这些字段可以包括它们声明的类型。

HIT 软件构造 5 :第4,5章复习

(2)重新赋值和不可变值

例如,如果我们有一个字符串变量s,我们可以将其从值“a”重新赋值为“ab”

String s=“a”;

s=s+“b”;

String是不可变类型的一个例子,这种类型的值一旦被创建就永远不会改变。不可变的对象(由它们的设计器设计为始终表示相同的值)在Snapshot diagram中用双边框表示,就像我们的图中的字符串对象一样。

不可变对象:用双线椭圆

HIT 软件构造 5 :第4,5章复习

(3)可变值

可变值

StringBuilder(一个内置的Java类)是一个表示字符串的可变对象,它具有更改对象值的方法:

StringBuilder sb = new StringBuilder("a");

sb.append("b");

HIT 软件构造 5 :第4,5章复习

(4)不可变引用

不可变的引用: 只分配一次而从不重新分配的变量。

使引用不可变:使用关键字final声明它:

在Snapshot diagram中,不可变的引用(final)由双线箭头表示。

HIT 软件构造 5 :第4,5章复习

注:1. 引用是不可变的,但指向的值却可以是可变的,例如:final StringBuilder sb

2. 可变的引用,也可指向不可变的值,例如:String s

二、设计规约

1. Specification前置/后置条件

(1)Specification(5.2.2)

规约(SpecificationContract):程序与客户端之间达成的一致

Spec给“供需双方”都确定了责任,在调用的时候双方都要遵守

功能:

1. 规约可以隔离“变化”,无需通知客户端

2. 规约也可以提高代码效率

3. 扮演“防火墙”角色,不需了解具体实现

对象与其用户之间的统一:1. 输入/输出的数据类型 2. 功能和正确性 3. 性能

只讲“能做什么”,不讲 “怎么实现”。

(2)前置/后置条件(5.2.4)

方法规约包含以下条目:

1. 前置条件(Precondition):对客户端的约束,在使用方法时必须满足的条件(requires)

2. 后置条件(Postcondition):对开发者的约束,方法结束时必须满足的条件(effects)

3. 异常行为

前置条件满足,则后置条件必须满足。

前置条件不满足,则方法可做任何事情。

静态类型声明是一种规约,可据此进行静态类型检查static checking。

前置条件:@param

后置条件:@return 和 @throws

规约不应该涉及方法的局部变量或方法类的私有字段。

HIT 软件构造 5 :第4,5章复习

除非在后置条件里声明过,否则方法内部不应该改变输入参数。应尽量遵循此规则,尽量不设计 mutating的spec,否则就容易引发bugs。

2. 行为等价性(5.2.3)

行为等价性:是否可相互替换

需要站在客户端视角看行为等价性。

根据规约,判断是否行为等价

例:对从前向后查找与从后向前查找而言,当要求有只出现一次时,便会等价。

HIT 软件构造 5 :第4,5章复习

HIT 软件构造 5 :第4,5章复习

3. 规约的强度

规约的强度 S2>=S1:1. S2前置条件更弱 2. S2后置条件更强

就可以用S2替代S1

条件强弱从集合上考虑是:弱的集合包含强的集合

例:出现多次包含出现一次,寻找一个包含寻找第一个

HIT 软件构造 5 :第4,5章复习

注:1. nothing是最弱的条件

2. 后置条件的调整需要在原来前置条件的基础上考虑

HIT 软件构造 5 :第4,5章复习

3. 当规范得到加强时:满足它的实现更少,更多客户可以使用它

上一篇:ubuntu18.04使用命令 sudo apt-get update出现源文件无法找到, 404 Not Found [IP: 91.189.95.83 80]


下一篇:案例分析——2020春HIT网络与社会导论