第四章 数据类型与类型检验
数据类型:
基本数据类型:int,double,long,boolean,char;对象数据类型:String;
区别:
静态类型检查:编译阶段报错,对类型的检查
语法错误,类名/函数名错误,参数数目错误,参数类型错误,返回值类型错误
动态类型检查:对值的报错
非法的参数值,非法的返回值,越界,空指针
不变性:
不可变数据类型:一旦被创建,其值不能被改变;
只能通过创建一个新的空间存储新的值来达到改变值的效果
final作为前缀:不能改变其地址,即:不可变的引用
故若不可变数据类型前用final,该变量不可更改
final+类:无法派生子类
final+变量:该变量无法改变值/引用
final+方法:该方法无法被子类重写
不变对象:一旦被创建,始终指向同一个值/引用
可变对象:拥有方法可以修改自己的值/引用
String是一个不可变对象
当有多个引用时,差异就出现了:
使用不可变类型,对其频繁的修改会产生大量的临时拷贝,需要垃圾回收,但安全
可变类型:适合于在多个模块之间共享数据
解决办法:防御式拷贝
Snapshot图
描述程序运行时的内部状态,便于刻画各类变量随时间变化
注意看PPT
抽象数据类型每个字段都有指向
一个列表的每一个index也都有指向
Final StringBuilder :一个不可变的引用和可变的值
第五章 设计规约
方法:规约+实现
规约:程序与客户端达成的一致,在调用的时候双方否必须遵守;客户端无需阅读调用函数的代码,只需理解spec即可;只讲“能做什么”不讲“怎么做”
行为等价性:
站在客户端视角看行为等价性;
根据规约:这两个函数符合这个规约,故他们等价
规约:
前置条件,对客户端的约束,在使用方法时必须满足的条件;
后置条件,对开发者的约束,方法结束时必须满足的条件;
如果前置条件满足了,后置条件必须满足;如果前置条件未被满足,方法可以做任何事情;
静态类型声明是一种规约,可据此进行静态类型检查;
Param:前置条件;throws和return:后置条件
方法的规范可以讨论方法的参数和返回值,但它不应该讨论方法的局部变量或方法类的私有字段。应考虑到该规范的读者是不可见的实现。
可变的方法:
除非在后置条件里声明过,否则方法内部不应该改变输入参数;即:除非spec必须如此,否则不应修改输入参数;
尽量避免使用mutable的对象:
程序中可能有很多变量指向同一个可变对象(别名);
只能靠spec来保证类的实现体和客户端不保存可变变量的别名;
尽量使用不可变的数据类型:eg. String
设计规约:
规约的确定性:一个输出or在一组输出中选择
规约的陈述性:描述了输出是什么还是明确的说明了如何计算输出
规约的强度:
spec变强:更松的前置条件+更严格的后置条件
越强的spec意味着程序员责任更重,客户端责任更轻
图示:程序员可以在规约的范围内自由选择实现方式,客户端无需了解具体使用了哪个实现;更强的规约表达为更小的区域
规约的质量:
内聚的,描述的功能应单一简单易理解,若规约做了两件事,要分离开形成两个方法;
不能太弱,应尽可能考虑到各种特殊情况,在后置条件中作出处理;不能太强,给开发者增加了实现的难度;
可以在规约中使用抽象类型,给方法的实现体和客户端更大的自由度(eg.用List而不是ArrayList);
是否使用前置条件取决于:
check的代价:若检查的代价太大,就写入前置条件,把责任交给客户端;也就是,可以不检查前置条件,因为是客户的责任
关于参数的合法性,倾向于不写在前置条件里,而是将其放入后置条件,当参数不合法时就抛出异常,并尽可能的fail fast。
方法的使用范围:如果只在类的内部使用该方法(private),那么可以不使用前置条件,在使用该方法的各个位置进行check,责任交给内部client;如果在其他地方使用该方法(public),那么必须要使用前置条件,若client端不满足则方法抛出异常。
标签:复习,后置,规约,前置条件,软构,数据类型,方法,客户端 From: https://www.cnblogs.com/777-Song/p/17426295.html