HIT 软件构造期末复习四 数据类型与数据检验

介绍:
静态,动态类型检查
可变,不可变数据类型
可变数数据类型的危险
不可变数据类型的危险
用Snapshot图理解数据类型
用集合类表达复杂数据类型

1.程序语言中的数据类

数据类型:是一组值的集合以及定义在这些值上的操作,如布尔类型,整形,浮点型,字符串等。
变量:用特定数据类型定义,可存储满足类型约束
JAVA中的数据类型
基本数据类型:int long double char
对象数据类型:String表示一个字符序列 BigInteger表示任意大小的整数等。
规定:根据Java约定,基本类型是小写的,而对象
类型以大写字母开始。
区别:

在这里插入图片描述
**对象类型的层次结构:**除了Object之外的所有类都有一个父类,用一个extends指定 ,Object是所有类的root。如果省略extends子句,默认父类为Object。类和父类是继承关系,即子类继承他的父类。
继承:继承父类的可见字段和方法 ,同时也可以覆盖方法来改变他们的行为
在这里插入图片描述

基本数据类型和对象数据类型的转换:
将基本类型包装为对象类型:– Boolean, Integer, Short, Long, Character, Float, Double;通常是在定义集合类型的时候使用它们,一般情况下,尽量避免使,一般可以自动转换。

数据操作
操作符:= + - * /
优先级:括号> 乘除> 加减
字符串连接:text = text + " number " + 5; // text = "hello world number 5

操作就是输入到输出的映射函数,其类型有:
作为中缀、前缀或后缀操作符:For example, a + b
作为对象的方法:For example, bigint1.add(bigint2)
作为一个函数:For example, Math.sin(theta)

重载(Overloading):
同样的操作名可用于不同的数据类型

2.静态类型检查和动态类型检查

在高级编程语言中存在数据类型的转换:
int a = 2; // a = 2
double a = 2; // a = 2.0 (Implicit)
int a = (int) 18.7; // a = 18
double a = (double)2/3; // a = 0.6666…
int a = 18.7; // ERROR
String a = 1; // ERROR
double a = 2/3; // a = 0.0

**静态类型语言:**所偶变量的类型在编译时(程序运行之前)已知,因此编译器可以推导出表达式的类型。如果a和b被声明为int类型,则编译器的出a+b也为int类型。再写代码时会报错正是由于编译时的类型检查。在编译阶段进行检查。bug通查在编译时可发现,避免了将错误带入到运行阶段,可提高程序正确性/健壮性,如:语法错误,类名/函数名错误,参数数目错误,参数类型错误,返回值类型错误。

动态类型语言:在程序运行时才进行检查,bug需要到代码被执行时才能发现,如:非法的参数值.(例如,整数只有当y实际上为零时,表达式x/y才会出错;否则它的工作原理。在这个表达式中,除以0不是静态错误,是动态错误),非法的返回值, 越界, 空指针

静态类型检查 >> 动态 >> 无检查
静态检查:关于“类型”的检查,不考虑值动态检查:关于“值”的检查。

例如:
在这里插入图片描述

3.可变性和不可变性

在高级语言中通常使用“=”给变量赋值
改变一个变量:将该变量指向另一个值得存储空间;
改变一个变量的值:将该变量当前指向的值得存储空间写入一个新的值

变化是“罪恶的”,当程序中不能没有变化,要尽可能避免变化,避免副作。

不变性是重要的设计及原则

不可变数据类型:一旦被创建,其值不能被改变。
要使引用不可变,请使用关键字final声明它
在这里插入图片描述
所以,尽量使用final变量作为方法的输入参数、作为局部变量。
final表明了程序员的一种“设计决策”
final类无法派生子类
final变量无法改变值/引用
final方法无法被子类重写

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

String是不可变类型的一个例子。
在这里插入图片描述
StringBuilder是可变类型的一个例子。
在这里插入图片描述
使用不可变类型,对其频繁修改会产生大量的临时拷贝(需要垃圾回收)
可变类型最少化拷贝以提高效率

使用可变数据类型,可获得更好的性能,也适合于在多个模块之间共享数据
使用不可变数据类型:更“安全”,在其他质量指标上表现更好

折中,看你看重哪个质量指标

集合类型是可变数据类型
下图是计算两个list的和的函数 一个式计算值得和,另一个式计算绝对值的和,由于是可变的,先计算绝对值之和会改变遍历内部的和,两次就够都会是10
在这里插入图片描述
DATA时间是一个可变数据类型
在这里插入图片描述
返回一个可变数据类型时,很可能会被接受着改变你内部的值,这存在风险。

好的做法是:
通过防御式拷贝,给客户端返回一个全新的Date对象
在这里插入图片描述

大部分时候该拷贝不会被客户端修改,可能造成大量的内存浪费
大部分时候该拷贝不会被客户端修改,
可能造成大量的内存浪费

▪ In both of these examples — the List and the Date — the problems would have been completely avoided if the list and
the date had been immutable types.

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

4.快照图 Snapshot diagram as a code-level, run-time, and moment view

快照图表示程序的内部状态运行时-它的堆栈(正在进行的方法及其局部变量)和它的堆(当前存在的对象)。
用于描述程序运行时的内部状态
便于程序员之间的交流
便于刻画各类变量随时间变化
便于解释设计思路

在这里插入图片描述
例如:我们有一个不可变数据类型String,我们初始化为a,现在需要使它为ab:
String s = “a”;
s = s + “b”;

不可变数据类型用双实线椭圆表示
在这里插入图片描述
反之对于可边数据类型StringBuild
在这里插入图片描述在这里插入图片描述

Java还提供了不可变引用:变量只分配一次,永不再分配。做一个参考不可变,用关键字final声明: final int n = 5;
在快照图中,不可重新分配的引用(final)是用双箭头表示。

一个对象的id永远不会改变(它不能被重新分配给
不同的数字),但其年龄可以改变:
在这里插入图片描述
一个不可变数据类型或 可变数据类型的final应用:引用是不可变的,但指向的值可以改变,如:final StringBuilder sb)
一个可变数据类型的final 可变的引用,也可指向不可
变的值:String s

在这里插入图片描述

s1首先指向abc,是不可变的
list是集合数据类型,是可变的,第三行把list的第0好元素指向s1
之后s1+d,由于s1不可变,所以s1指向一个新的空间,abcd;
s1旧的空间任然存在,list的第0好元素指向s1旧的空间abc
所以首先输出abc

之后创建s2为s1+e,开辟一个心空间,list的第0好元素指向s2
所以输出abcde
在这里插入图片描述

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

Array
固定长度的序列,创建时需要指定长度,一旦创建长度不可再改变。
int[] a = new int[100]:int[]指明每一个元素是整数
Operations on array types include:
– indexing: a[2]
– assignment: a[2]=0
– length: a.length

List
可变长度的序列,创建时不用指定长度;
List list = new ArrayList():Integer指明每一个元素是整数,<>括号中必须是对象;
在这里插入图片描述

Some of its operations:
– indexing: list.get(2)
– assignment: list.set(2, 0)
– length: list.size()

List和array很相似,但又不同,看一个遍历的例子:
在构造器中可以使用基本数据类型
在这里插入图片描述

Set
Set是零个或多个唯一对象的无序集合。
一个对象不能多次出现在集合中。要么在要么不在
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(图):每个元素是对值key-value,每个key只有一个value
操作:
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
在这里插入图片描述

当我们添加一个项目时,编译器可以执行静态检查
确保只添加适当类型的项。
然后,当我们拿出一件物品时,我们就能保证它的类型
将是我们所期待的。

定义方法:
List cities; // a List of Strings
Set numbers; // a Set of Integers
Map<String, Turtle> turtles; // a Map with String keys and Turtle values

<>中必须是对象数据类型,不能是基本数据类型

Implementations of List , Set , and Map :
– List: ArrayList and LinkedList
– Set: HashSet
– Map: HashMap

迭代器
迭代器是一个逐步遍历集合元素的对象,一个接一个的遍历。
由两部分组成:
next()返回集合中的下一个元素——这是一个mutator方法!
hasNext()测试迭代器是否到达集合的末端。

6.使用不可变数据类型

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

如果需要使用较大的数字进行计算,可以使用BigIntegerBigDecimal是不可变的。

Java集合类型的常见实现:List、Set、
Map -都是可变的:ArrayList, HashMap等。

Collections实用工具类具有获取这些可变集合的不可修改视图的方法:
– Collections.unmodifiableList
– Collections.unmodifiableSet
– Collections.unmodifiableMap
这种包装器得到的结果是不可变的:只能看
但是这种“不可变”是在运行阶段获得的,编译阶段无法据此进行静态检查

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值