软件构造复习2

自用。

一、基本数据类型、对象数据类型

基本数据类型:int、long、boolean、double等,——有值,无ID,无法区分,不可变,在栈中分配内存,代价低;

对象数据类型:String、Date等——有值,有ID,可为可变也可为不可变,在堆中分配内存,代价昂贵;

可将基本数据类型包装为动态数据类型(首字母变大写)通常在定义集合类型时使用,一般避免使用,一般可自动转换

二、静态类型检查,动态类型检查

静态类型检查(编译阶段检查)》动态类型检查(运行阶段检查)》无检查

那么静态类型检查检查哪些呢?其包括语法的检查,函数名,参数返回值类型个数的检查等;而动态类型检查则检查非法的值和越界空指针等

——简而言之,静态检查:是关于“类型”的检查,不考虑值;动态检查:关于“值”的检查

三、mutable/immutable,值的改变、引用的改变、final

不变对象:一旦被创建,始终指向同一个值/引用;可变对象:拥有方法可以修改自己的值/引用

其中,如课件的例子,我们可以知道string是不可变(concat会新建一个引用)的,而stringbuilder是可变的。不可变类型会更安全,而可变的数据类型性能会更高(在有多个引用时会很不安全)

final表示值只能被赋值一次,static修饰的数据会被存放在静态内存中而非使用一次就被释放。

四、防御性拷贝、

防御性拷贝——对于可变数据类型的弥补,为防止用户获得某些ADT属性后进行修改进而对ADT造成巨大影响而采用。

其具体操作可以return一个new的对象

五、Snapshot diagram

其用于描绘程序运行时的内部状态,便于内部人员交流,刻画,解释,“不可变”用双线。

针对可变值的不可变引用——eg:final stringbuilder,可以被加字符,不能被重新赋值。

针对不可变值的可变引用——eg:string

(迭代器补充——是一个超级接口,可以遍历集合的对象——两个方法next(),hasnext())

七、Specification、前置/后置条件、行为等价性、规约的强度

方法的两个“设计决策”——代码蕴含(实现体)的给编译器读,注释形式(规约)的给自己读。

行为等价性——对用户来说可替换(可采用不同实现)——根据规约来判断。

前置条件满足,后置条件(return)必须满足,否则方法可做任何事。

规约强度:spec变强意味着更放松的前置条件+更严格的后置条件(“更小的区域”)

八、ADT操作的四种类型

ADT(自己定义的抽象数据类型)与表示独立性:“避免表示泄露(客户端获取数据内部表示)”

四种类型:构造器、生产器、观察器、变值器(可变数据类型专属)

1、构造器:构造函数或静态函数——进行初始化,构造方法名必须与类名相同,可以定义多个构造方法,没有返回值。

2、构造函数的调用——子类只调用父类默认构造函数,子类必须调用父类的构造函数。可以通过系统自动调用父类的默认构造函数,如果父类没有默认构造函数时,子类构造函数必须通过super调用父类的构造函数。

3、构造器是从无到有(或不同类型),而生产器是从旧到新(皆为同类型),eg:String.concat()

九、表示独立性,表示泄露、不变量、表示不变量(RI)、表示空间、抽象空间、AF抽象函数与以注释形式表示RI,AF

表示独立性:client使用ADT时无需考虑其内部如何实现,ADT内部表示的变化不应影响外部spec和客户端。同时,除非规约要求,否则不应该修改内部表示

不变量——任何时候总是为true(eg:immutability),由ADT负责保持其不变量以保证正确性。

表示泄露会影响独立性,正确性——如何避免表示泄露:确保变量为private(是否为final无所谓),尽量采用不变数据类型,或采用防御性拷贝,随时检查RI是否满足。

表示空间是ADT内部可见的成员变量取值、抽象空间是client可见的部分、AF抽象函数表示了R和A之间的映射关系——“你用的东西是什么意思”。

AF、RI写在注释中,所以不会被除自己以外的人看到,涉及内部实现

目的:在编程过程中为我们提供指导和约束,在设计好后,我们的所有工作都必须在这个前提下进行

在进行编写时应满足——RI:针对Rep的每一个field以及多个fields之间的关系,进行条件限定,要精确,AF:给出client看到的A值是什么,是对每一个Rep值的“数学运算”

十、接口、抽象类、具体类

接口和类用以实现ADT,接口之间可以继承与扩展,一个类可以实现多个接口,同理,一个接口可以有多种实现类

具体来说,接口用以确定ADT规约,类用以实现ADT(也可以不用接口)

接口内可以实现静态工厂方法以构造对象, 还可以用default方法在接口中统一实现某些功能(重点在于统一实现)

如图

接口内无法定义一般的成员变量(定义必须以public static final修饰)

抽象类:不能被实例化,可以被继承。

若一些方法所有子类不同但各由不同,则可以设置为抽象方法,将父类设置为抽象类。

抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类,抽象类中的抽象方法只是声明,不包含方法体。

抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

十一、继承、重写(override)

子类继承父类后就有了其属性、方法(不支持多继承)

override(重写)是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!

可用super来调用父类方法

重写的一些规则:不应改变方法本意、重写方法不能比被重写方法限制有更严格的访问级别、

重写方法不能抛出新的异常或者比被重写方法声明的检查异常更广的检查异常,但是可以抛出更少,更有限或者不抛出异常、不能重写被标识为final的方法、如果一个方法不能被继承,则不能重写它等

十二、多态、重载(overload)

多态就是同一个接口,使用不同的实例而执行不同操作

无论重载、泛型,还是继承关系都是多态的一个具体表现,也被归属为不同的多态

多态分为:

特定多态:函数重载,操作符重载(Java只有内建的操作符重载)

参数化多态:泛型

子类型多态:表示有替代关系,有子类型关系,可以替换,由继承决定

重载:多个方法具有同样的名字,但有不同的参数列表或返回值类型(重点)——方便client调用,client可用不同的参数列表,调用同样的函数

十三、泛型

参数化多态机制:指在程序设计语言中声明与定义函数、复合类型、变量时不指定其具体的类型,而把这部分类型作为参数使用,使得该定义对各种具体类型都适用。

被称为泛型函数、泛型数据类型、泛型变量、形成了泛型编程的基础。(不同种类的参数)

十四、等价性equals()和==,equals()的自反、传递、对称,hashcode

==:引用等价性,比较基本数据类型时可用;equals:对象等价性——自定义ADT时需要重写(可变类型不必重写,继承(实现行为等价性)即可),比较对象数据类型时可用

重写准则——自反、传递、对称(等价性),除非对象被改,否则多次调用equals应该是同样的结果,相等对象的hashCode结果必须一致,任何值与null值比较都返回false

扩展:instanceof是Java的一个二元操作符,返回一个布尔值,判断左边的对象是否是它右边的类的实例,但应尽量避免使用;getClass()方法是获得调用该方法的对象的类

下图来自网络

hashcode:返回当对象放入hash容器中后产生的哈希值(一个整数),用于判断是否是同一个对象

要求与equals逻辑一致,可以直接return一个整数

十五、不可变对象的引用等价性、对象等价性,可变对象的观察等价性、行为等价性

对于不可变对象:只能观察,一般需要重写equals,hashcode

对于可变对象:

观察等价性:不改变状态的情况下看起来一致;行为等价性:调用对象任何方法得到的结果一致

不同mutable类有不同的等价性标准,其equal不必重写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值