软件构造课程阶段总结(三):数据类型与类型检验

前两篇回顾了什么是高质量软件,如何从不同维度刻画软件、软件构造的基本过程和步骤,本篇关注软件构造的理论基础ADT(抽象数据类型)和软件构造技术基础OOP(面向对象编程)

编程语言中的数据类型

Java中的类型与变量

数据类型:一组值以及可以对其执行的操作

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

Java语言包括基本数据类型和对象数据类型。

  • 基本:int long boolean double等
  • 对象:string等

根据Java约定,基本体类型为小写,而对象类型以大写字母开头。

  • 原始数据类型:只有值,没有ID(无法区分);不可变的 ;在栈中分配内存;代价低
  • 对象数据类型:既有ID,也有值;可变或不可变;在堆中分配内存;代价昂贵

对象类型形成层次结构

所有非原始类型的根类型都为Object

如果省略了extends语句,则默认继承自Object

一个类是其所有父级类的一个具体类型

  • 类可以从它的父级类中继承可见的字段和方法
  • 类可以覆盖继承的方法来改变它们的行为

包装原始类型

Boolean, Integer, Short, Long, Character, Float, Double

将基本类型包装为对象类型,通常是在定义集合类型的时候使用它们,一般情况下,尽量避免使用。

一般可以自动转换。

操作、操作符

操作符

简单的计算符号:=,+,-,*,/

字符串链接(+)

String text = "hello" + " world";
text = text + " number " + 5; 
// text = "hello world number 5"

 操作

接受输入产生输出的函数。

作为中缀、前缀或后缀运算符。例如,a + b调用操作=: int × int → int 。

作为一个对象的一种方法。例如,bigint1.add(bigint2)调用操作add:BigInteger × BigInteger → BigInteger 。

作为一个函数。例如,Math.sin(theta)调用操作sin:double → double 。在这里,Math不是一个object。它是一个包含sin函数的类。

重载

有些操作被重载,因为相同的操作名称用于不同类型。

对于Java中的数字原始类型,算术运算符
+、-、*、/被大量重载。

方法也可以被重载。大多数编程语言都有一定程度的重载。

静态与动态数据检查

类型转换

int a = 2; // a = 2 
double a = 2; // a = 2.0 (隐式类型转换) 
int a = (int) 18.7; // a = 18 
double a = (double)2/3; // a = 0.6666…

静态类型/动态类型

  • Java是一种静态类型语言:

所有变量类型在编译时已知,因此编译器可以推导表达式类型

IDE在编写代码时就执行静态类型检查,编译阶段进行类型检查

  • Python为动态类型语言,在动态类型语言中检查延迟到程序运行时

一种语言可以提供的三种自动检查:

  • 静态类型检查:在程序运行之前就会自动发现错误。
  • 动态类型检查:在执行代码时会自动发现错误。
  • 不检查:该语言根本不能自动找到错误。

静态地捕捉一个bug比动态地捕捉它要好,而动态地捕捉它也比根本不捕捉它要好。

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

静态类型检查

可在编译阶段发现错误,避免了将错误带入到运行阶段,可提高程序正确性/健壮性

  • 语法错误:比如额外的标点符号或假词。即使是像Python这样的动态类型语言,也会进行这种静态检查。
  • 错误地命名了类名/函数名错误,如Math.sine (2)。(正确的名字是sin)
  • 参数数量错误,比如Math.sin(30,20)。
  • 参数类型错误,如Math.sin(“30”)。
  • 返回值类型错误,如从声明返回int的函数返回了“30”。

动态类型检查

  • 非法参数值。例如,整数表达式x / y只有在y实际上是0时才是错误的;否则它就能工作。所以在这个表达式中,除以零不是一个静态错误,而是一个动态错误。
  • 非法的返回值,即当特定的返回值不能在该类型中表示时。
  • 超出范围的索引越界,例如,在字符串上使用一个负的或太大的索引。
  • 调用空对象引用上的方法。(空指针)

总的来说,静态检查是关于类型的检查,不考虑具体值;动态检查是关于值的检查。

可变性与不可变性

可变性与不可变性

Java语言中,改变一个变量、改变一个变量的值,二者有区别:前者是将该变量指向另一个存储空间;后者是将该变量当前指向的存储空间中写入一个新的值。

程序编写需要尽可能避免变化。

关于不变性的设计:不变数据类型。一旦被创建,其值不能改变,引用类型也可以不变(指向对象不变)。

不变对象:一旦被创建,始终指向同一个值

可变对象:拥有方法可以修改自己的值(引用)

具体方法:

final

final int n = 5;

final Person a = new Person(“Ross”);

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

所以,尽量使用final变量作为方法的输入参数、作为局部变量。final表明了程序员的一种“设计决策”。

  • final类无法派生子类
  • final变量无法改变值/引用
  • final方法无法被子类重写

String/StringBuilder

String:

是不可变类型,要在末尾添加内容,必须创建一个新的新的字符串对象

StringBuilder:

可变类型,可以删除、替换、插入等,类有更改对象值的方法。

区别、优缺点

可变优点:

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

可变类型最少化拷贝以提高效率。

使用可变数据类型,可获得更好的性能。

也适合于在多个模块之间共享数据。

不可变优点:

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

实际使用时需要折中考虑,取决于看重哪个质量指标。

使用可变数据类型时防范风险

防御式拷贝(安全,但容易造成内存浪费)

在此种情况下使用不可变类型可以防范风险,节省复制代价

安全的使用可变类型:局部变量,不会涉及共享;只有一个引用

如果有多个引用,则使用可变类型则就不安全

快照图

快照图表示一个程序在运行时的内部状态——它的堆栈(正在进行中的方法及其本地变量)和它的堆(当前存在的对象)。

优点:

  • 便于程序员之间的交流
  • 便于刻画各类变量随时间变化
  • 便于解释设计思路

快照图类型:

基本类型:

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

 

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

重新分配值

  • 不可变对象:双线椭圆
  • 可变对象:单线椭圆
  • 不可重新分配的引用:双箭头

(引用不可变,但指向的值可变;可变的引用指向的值可以不可变)

复杂数据类型:数组和集合

Array:

数组是另一种类型T的固定长度的序列。

int[]数组类型包括所有可能的数组值,但一个特定的数组值一旦创建,就永远不能更改其长度。

对数组类型的操作包括:

indexing: a[2]
assignment: a[2] = 0
length: a.length

List:

列表是另一种类型T的可变长度序列。

对列表的一些操作:

indexing: list.get(2)
assignment: list.set(2, 0)
length: list.size()

Set: 

集合是包含零个或多个唯一对象的无序集合。

对象不能在集合中出现多次。

对集合的一些操作:

s1.contains(e)      //test if the set contains an element
s1.containsAll(s2)  //test whether s1 ⊇ s2
s1.removeAll(s2)    //remove s2 from s1

Map:

映射类似于一个字典(键-值)。

对映射的操作:

map.put(key, val)    //add the mapping key → val
map.get(key)         //get the value for a key
map.containsKey(key) //test whether the map has a key
map.remove(key)      //delete a mapping

 

实用不可变类型:

基本类型及其封装类型都是不可变的。

如不要使用可变的Date,使用与需求匹配的不可变类型。

List, Set, Map的具体实现类都是可变的,Collection类有一些方法来获取这些可变集合的不可修改的视图

用途:

在集合构建后使其不可变。

允许某些客户端只读访问您的数据结构。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值