软件构造的理论基础-ADT
软件构造的技术基础-OOP
1.编程语言中的数据类型
类型和变量
类型是变量的集合,在这些变量集合上我们可以定义运算(类似于代数系统?)。栗子:boolean,int,double,String
变量是被命名的位置,这里存储着着一个特定的值。类似于萝卜和坑的关系。
java中的类型
java的基本数据类型:
int,long,char
java的对象数据类型
String,BigInteger
java中基本数据类型的字母都是小写的,而对象数据类型词节首字母大写
基本数据类型 | 对象数据类型 |
int,long,byte,short,char,float,double,boolean | classes,arraya,enums |
只有值,没有ID | 既有值又有ID |
不可变 | 可变/不可变 |
栈中分配内存 | 堆中分配内存 |
无法实现表达的统一 | 采用泛型实现表达的统一 |
代价低 | 代价昂贵 |
对象类型构成层次结构
根是Obiect,一切类都有父类除了Object,因为他是所有类的祖先。
类是其所有超类的实例:继承了看得见的域和方法从他的超类。无法重写方法改变他们的行为。
包装类型
定义容器类型,会降低性能,可以自动转换
操作符
是一种函数,
重载
同样的操作名可用于不同的数据类型
2.静态和动态类型检验
java是一个静态类型语言,变量的类型在编译的时候就知道了,在程序运行之前(编译阶段进行类型检查)
Python是一个动态类型语言,在运行的时候进行类型检查。
三种检查机制:静态检查,动态检查,无检查(你得自己找错误)
从前往后的自动程度依次递减。
不匹配类型
然而java没有不匹配类型(有点爽)
静态检查
静态类型检验意味着在编译的时候就检查程序中可能出现的bug。
- 语法错误:python也有(虽然他是静态类型语言)
- 类名、函数错误
- 参数数目错误
- 参数类型错误
- 返回值类型错误
动态检查
- 非法的参数值(除零操作)
- 非法的返回值()
- 越界
- 空指针
静态检查vs动态检查
静态检查关注值的类型,但是并不关注值到底是多少,只有运行之后才知道(无法发现除零或者或者数组越界的错误)
动态检查,相反的,更加关注具体的数值导致的错误
基本类型不是真的数字
因为计算机本身的原因,有时候基本类型做运算得到的结果并非是真正正确的结果
比如 int a; a=3,a/2=?
3.可变与不可变
改变一个变量或者他的值
这二者有何区别?
改变一个变量,将该变量指向另一个值的存储空间
改变一个变量的值,写入一个新的值
不变性
引用类型也可以是不可变的,一旦确定他指向的对象,就不能再变动了。
final是一个很好的让对象不可变的关键词(直接阉割,永绝后患)
final无法派生子类(东方不败无法生孩子)
final无法改变值/引用(太监很忠诚,不会改变自己的对象)
final方法无法被子类重写。
不变与可变
String是一个不可变类型
为了加入新的字符串,我们需要创建新的对象。
StringBuilder是一个可变类型
可变类型的优点
使用不可变类型,对其频繁修改会产生大量的临时拷贝
可变类型最小化拷贝以提高效率
可变数据类型可以获得最好的性能
也适合在多个模块之间共享数据
可变类型的缺点
不安全(例子中改变了输入参数的值)、难以理解
如何规范编程
防御式编程 返回一个全新的对象,然而,大部分时候该拷贝不会被可不断修改,造成大量的内存浪费
不可变类型不需要防御式拷贝
别名使用导致可变类型危险
安全的使用可变类型:局部变量、不会涉及共享,只有一个引用
4.代码快照图在代码级别,运行时,时刻角度
不可变对象-双线椭圆
不可变引用-双线箭头
引用是不可变的,但指向的值却是可变的,可变的引用,也可指向不可变的值。
栗子:针对可变值的不可变引用,final StringBuilder sb =new StringBuilder(“abc”)
5.复杂数据类型:Arrays and Collections
Array
就是定长数组
List
List是一个接口,其中的成员必须是对象
Set
无序集合
Map
类似于字典,键值对
关于List,Set,Map的一些声明
添加成员时会进行静态检查,确保只添加合适类型的成员
无法创造一个容纳基本数据类型的容器
ArrayList,LinkedList。HashSet,HashMap.
迭代器作为一个可变类型
next和hasNext
(这里的例子记得要注意)
6.有用的不可变类型
基本类型及其封装对象类型都是不可变的
7.空引用
空对象.xxx调用非静态方法或属性都会出现空指针异常;