软件构造这门课是比较具有挑战性,知识点多且琐碎的,因此,我将结合ppt和回放,对软件构造的知识点来进行整理,主要用于对于知识点的记忆和复习,如果能够对你有所帮助,那荣幸之至。
在这篇博客中,我将对第三章 3.1 这节的知识点来进行整理总结。
3.1 数据类型与类型检验
3.1.1 数据类型
数据类型,可以看做是具有相似性质的数据所构成的集合,对于java来说,有两种数据类型,分别是基本数据类型和面向对象的数据类型,两者最主要的区别便是在内存中存储的位置不同,基本数据类型存储在栈中而对象数据类型则是存储在堆当中。
两种数据类型的区别:
对象数据类型具有层次性,即几个对象数据类型之间可以有继承关系,通过extens或者implements实现。继承具有严格的语义关系,比如B继承A,则表明任何的B都是A,他们具有行为一致性。
3.1.2 类型检测
类型检测主要分为两种,静态类型检测和动态类型检测,静态类型检测主要是针对数据类型是否正确的检测,因此静态类型检测不需要运行程序,而是在编译阶段完成检测。
静态类型检测的内容:
相对的动态类型检测则是检测那些只有在运行的时候才会暴露出来的错误,例如在一个除法中,除数为0。
动态类型检测的内容:
值得一提的是,动态检测强于静态检测强于不检测,而程序的错误往往是类型使用的错误。针对java,只做静态检测。
3.1.3 可变性与不可变性
在程序运行的过程中,肯定避免不了对于某些变量进行修改。对于变量的修改主要有两种方式,直接改变一个变量的值或者改变一个变量。对muttable的变量,修改时直接改变其值
而对于immutable的变量,我们对其进行修改的时候,则是会创建一个新的内存区域,然后将变量指向新的内存区域
与不变性有关的关键词final,能够限定变量的指向不能够被改变。
判断一个变量是mutable还是immutable变量,若是不变的,则一旦被创建之后,始终指向同一个值/引用,如果是可变对象,则拥有方法可以修改自己的值/引用。当有多个引用指向同一个变量时,两种类型就出现区别了
对于immutable类型的变量,对于一个变量的修改不会影响其他的变量。这么来看,使用mutable类型的变量有危险性,但是也有好处,比如能够减少频繁的拷贝从而提高程序的效率。使用哪种变量需要进行取舍。
mutable危险性的一个例子:
在这个例子中使用了mutable类型的List,在执行第一个打印语句后,list中的元素已经被修改为5,3,2,因此两条打印语句都会输出10,显然,这是与规约不相符合的,同时程序员也很难发现这类错误。
一个immutable类型的变量不应将自己的属性暴露出去,比如下面这个例子:
在 return groundhogAnswer被执行后,partyDate和groundhogAnswer指向了相同的内存区域:
对其中任何一个的修改都会改变另外一个的值。
一个使程序变得更加安全的方法是防御性拷贝,即不直接返回引用,而是返回一个新的对象,就像这样:
一个引用暴露的例子:
当调用函数出现下面这些情况时
代码都会出现错误
经过防御式改造后的代码:
3.1.3.1将mutable变量转化为immutable变量
1.无任何可以修改属性的方法
2.属性都是private
3.返回时不会将属性暴露出去
3.1.4 Snapshotdiagram
用来表示对象在内存中分配情况,即从运行时,瞬时的,代码角度这三个维度来看。下面展示不同数据类型的画法:
在snapshotdiagram中,双线代表不可变的,比如说双线的椭圆表示这是一个immutable的变量,双线的箭头则表示该变量被final限定了。从snapshotdiagram图中,可以直观的发现,如果一个变量是immutable类型,且被final限定住了,则该变量永远不会改变。