本章主要介绍了在java的面向对象编程和ADT设计中常见的数据类型及其特性,以及相关的检查方式和优缺点。
(一)编程语言中的数据类型
数据类型是指一组值和可对其进行的操作,使用数据类型的约束来定义的值就是变量。java中分为基本数据类型和对象数据类型两种,其区别如下图:
可以通过包装来把前者变为后者,一般用在定义容器类型时使用包装(因为容器类型操作的元素要求是对象类型。对数据类型的操作可以是操作符(如加减乘除),方法和函数。
(二)静态与动态类型检查
静态检查在编译时 进行,而动态检查在运行时进行。静>动。
静态检查包括语法、名称、参数数目与类型、返回值类型等;动态检查包括非法参数值与返回值、越界和空指针等。
(三)可变与不可变
不变数据类型一旦被创建就不能改变值。不变性则是设计原则,需要借助final让可变的量也不可被修改。
对于不变量以String s为例,指向"a"后再赋值为“ab”时就会指向一个新的位置,而非在原位置上把a改成ab;可变量则相反。
优缺点:可变类型可最小化拷贝提高效率,性能更好也更适合共享数据;但不可变类型更安全,在其他质量指标上更优秀。而且,传递可变类型的数据会有发生错误修改的隐患,因此要进行防御式拷贝,且保证可变类型变量没有多个别名。
(四)多种视图下的快照图
快照图描绘的是程序运行时的内部状态。基本类型用箭头,对象类型则用椭圆加箭头。不可变对象用双线椭圆不可变的引用用双线箭头
其中有两种特殊的引用:一是可变值的不可变引用,比如final StringBuilder sb=new……就可以修改sb的值,但一旦将sb重指向另一个对象,就会编译出错;二是不可变值的可变引用,比如如下操作中,s1本身是不可变的,但List作为容器可以改变0索引处的指向。
(五)复杂数据类型:数组与集合
数组Array定长不可改变,而List则可以随意添加特定类型的元素;Set集合同样允许添加与删除元素,但其中是无序的;Map类型的元素为(key-value)的二元对,可以根据key的值对value进行操作,也同样支持单独提取出key集合或value集合。在对后三种容器添加元素时执行静态检查,可保证取出的值为指定类型。
(六)常见不可变类型
基本类型与其封装对象都不可变。
可以使用final得到不可变的原可变类型,同理可以使用Collection.unmodifiableX得到List,Set和Map的不可变版本。但以上包装得到的不可变类型出自运行时,编译阶段无法静态检查。