软件构造笔记 03

数据类型基础知识

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

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

java中包括基本数据类型和对象数据类型,二者对比情况:

基本数据类型对象数据类型
int, long, byte, short, char, float, double, booleanClasses, Interfaces, arrays, enums, annotations
只有值,没有ID(与其他值无法区分)既有ID,也有值
不可变的(immutable)一些可变(mutable),一些不可变
在栈中分配内存在堆中分配内存
无法实现表达的一致可以实现表达和泛型的一致
代价低代价高

对象类型的层次结构:

继承: 如果类A继承了类B,A称为B的子类,B称为A的超类,子类会获得超累所有可见的实例域和方法,并且可以通过重写来改变方法的行为,Java中所有的类都继承自Object类,如果一个类没有显式地继承一个类,则会继承Object。

包装基础数据类型: 通过将基础数据类型包装为对象数据类型(Boolean,Integer,Short,Long,Character,Float,Double)以实现表达的一致性,通常实在定义容器类型时使用,但会降低性能,故在一般情况下尽量避免使用。

//e.g.
List<Integer> list = new Array<Integer>();
list.add(1);
//1不是Integer对象类型,但编译能自动完成转换,但会降低效率,等价于
list.add(Integer.valueof(1));

静态/动态类型检查

静态类型语言(如java): 所有变量的类型在编译时已知,因此编译器可以推导表达式类型,在编译阶段进行类型检查。

例:如果变量 a 和变量 b 被定义为 int 型,编译器会推导出 a+b 也是 int 型。

动态类型语言(如Python): 在运行阶段进行类型检查

静态检查内容

为关于类型的检查,在编译阶段进行检查,避免将错误带入到运行阶段。

  • 语法错误(动态类型语言也会进行此类检查)
  • 类名/函数名错误
  • 参数数目错误
  • 参数类型错误
  • 返回值类型错误

动态检查内容

为关于值的检查,如除零错误。

  • 非法的参数值
  • 非法的返回值
  • 越界
  • 空指针

可变性和不可变性

两种变化

改变一个变量: 将该变量指向另一个存储空间

改变一个变量的值: 在该变量指向的存储空间中写入一个新的值

变化是麻烦的源头,但程序不能没有变化,好的程序员应该尽可能避免变化以避免副作用。

不变性

不变性: 一种重要的设计原则

不变数据类型: 一旦被创建, 其值不能改变

不变引用: 一旦确定其指向的对象,不能再改变指向其他对象,如Java中的 final 关键字

关于final的补充:fianl类无法派生子类,final变量无法改变值或引用,final方法无法被子类重写

可变对象与不可变对象

不可变对象: 一旦被创建,始终指向同一个值或引用,如String类

对于不可变对象String执行如下代码:

String s = "a";
s = s.concat("b");//这一方法并不会改变原先的值,而是创建一个新的String对象

不可变对象: 拥有方法可以修改自己的值或引用,如StirngBuilder类

对于可变对象StringBuilder执行类似代码

StirngBuilder sb = new StringBuilder("a");
sb.append("b");

二者对应的snapshot diagram如下:
可变对象与不饿扁对象
在上述例子中,只有一个引用指向该对象,二者并没有区别,但有多个引用时,差异就出现了

在上述代码的基础上继续执行:

Sting t = "c";
t = t + "c";

StringBuilder tb = sb;
tb.appedn("c");

二者对应的snapshot diagram如下:
多引用,可变对象与不可变对象
可变对象的优点: 在使用不可变类型时,对其频繁修改会产生大量的临时拷贝,而可变类型往往会进行最小化拷贝以提高效率,并且可变类型也适合在多个模块之间共享数据。

但是可变性可能使得难以理解程序在做什么,更难满足方法规约,此时不可变类型更加安全,在其他质量指标上表现更好。

可变对象的风险:

  • 传递可变值: 将一个可变对象作为方法的参数传入 ,若该方法在无意中改变了这个对象的值,则方法外部的对象也会随之改变,会产生难以察觉的错误,同时,这样的程序会变得难以理解。
/**@return the sum of the number in the list */
public static int sum(List<Integer> list){
	int sum = 0;
	for(int x : list)
		sum += x;
	return sum;
}

/**@return the sum if the absolute values of the numbers in the list */
public static int sumAbsolute(List<Integer> list){
	// let's reuse sum(), first wi take absolute values
	for(int i = 0; i < list.size(); ++i){
		list.set(i, Math.abs(list.get(i)));
	return sum(list);
}

// meanwhile, somewhere else in the code...
public static void main(Stirng[] args){
	List<Integer> myData = Arrays.asList(-5, -3, -2);
	System.out.println(sumAbslute(myData));         //the list myData will change to [5, 3, 2]
	System.out.println(sum(myData));                //the result will be 10
}
  • 返回可变值: 将一个可变对象的值作为返回值,在接收该变量并改变其值后,可能会产生错误。
/** @return the first day of spring this year */
public static Date startOfSpring(){
	if(groundhogAnswer == null)
		groundhogAnswer = askGroundhog();
	return groundhogAnswer;
	static Date groundhogAnswer = null;
}

public static void main(String[] args){
	Date partyDate = startOfSpring();
	partyDate.setMonth(partyDate.getMonth() + 1);
	Date homeDate = startOfSpring();  //what the homeDate wiil be?
	
}

安全使用可变对象:

  • 在仅有一个引用时使用,如作为局部变量使用
  • 防御式拷贝,返回一个全新的对象,但是可能造成内存浪费,而不可变对象不需要防御式拷贝
	return new Date(groundhogAnswer.getTime());

复杂数据类型

Array: 数组是另一种数据类型T的定长序列

List: List是另一种数据类型T的边长序列

Set: Set是0个或多个唯一对象(互不重复)的无序集合

Map: Map是一种类似字典的(key-value)集合

Iterator: 一个遍历一组元素并逐个返回元素的对象

不可变包装

List,Set,Map的通用实现是可变的,Collections 类可以获得这些可变集合的不可变观察,这种 “不可变” 实在运行阶段获得的,编译阶段无法据此进行静态检查

List<String> list = new ArrayList<>();
list.add("ab");
List<String> listCopy = Collections.unmodifiableList(list);
listCopy.add("c");  //执行时会抛出异常
list.add("c");
System.out.println(listCopy.size()); //如果注释掉抛出异常的代码,输出值为2

两种主要用法:

  • 当集合构建完成后将其转变为不可变类型
  • 对特定用户对数据结构访问设置只读权限
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值