目录
前言
在该部分中,学习了Java语言中数据的类型以及可变不可变类型的区别及其各自的优缺点,同时对数据类型的检验方法也进行了学习,在此进行系统的总结。
1.数据类型
1.1基本数据类型
例如int, long, short等,对于基本数据类型来说,它们只有值,没有ID,所以彼此之间无法区分。比如1,a,3.14等,它们所具有的就是它们本身,两个相同的值之间没有区别。它们是不可变的,即一旦确立,就无法在进行改变。内存分配在栈中。
1.2对象数据类型
例如Classes,interfaces,arrays等,与基本数据类型不同,对象数据类型除了有值之外,还有ID,相同的值之间也可以凭借不同的ID进行区分。有些对象数据类型是可变的,有些是不可变的,它们在堆中分配内存。
2.数据类型检查
2.1静态检查
静态检查在程序运行之前,也就是在编译阶段发现错误。在静态检查中主要检查代码中存在的语法错误、类名/函数名错误、参数类型或数目错误、返回值类型错误等。可以看出静态检查往往是检查类型的错误,与变量所具有的值无关。
在程序运行前检查出错误并改正,避免存在错误的代码还去运行,提高了程序的健壮性。
2.2动态检查
动态检查是在程序运行时发现错误。在动态检查中主要检查非法的参数值,非法的返回值,索引越界,空指针等,与静态检查不同,动态检查往往是关于由特定的值引起的错误。
2.3特殊情况
由于Java语言的原因,一些本该在动态检查阶段被检查出来的错误却不会被发现,需要我们在编程时特别注意。
- 整数除法返回的不是一个分数或小数,而是被截断的整数部分。例如3/2返回1。
- 整数溢出如果计算的结果太大超出了数据类型表示的范围,就会溢出,但对此并不会报错,而是给出一个随机的错误答案。使人不容易发现。
- 浮点特殊值NaN (“Not a Number”), POSITIVE_INFINITY, and NEGATIVE_INFINITY。例如对-9开平方时,就会返回一个NaN,而不是报错。表示这不是一个数。
3.可变性和不变性
3.1变量与变量的值
在讨论可变性和不变性之前,我们要先搞清两个概念,那就是改变一个“变量”,和改变一个“变量的值”。
从概念上来讲,改变变量,改变的是这个变量指向的空间,而改变变量的值,改变的是该变量指向空间内的值。
下面通过一个形象的例子来理解这个概念。我们将变量指向的空间看做一个盒子,空间内存储的值看做小球。改变变量即抛弃原本的盒子,而原本盒子内的球也不去改变,而我们又拿出了一个新的盒子,放入了新的小球。改变变量的值即在原本的盒子中放入了新的小球,而盒子本身并没有改变。
3.2不变性与可变性
不变性在数据类型和引用类型上都有体现。不变的数据类型是指该数据一旦被创建,其值就不能再去改变。而不变的引用类型是指确定了指向的对象后,就不能再改变指向其他的对象。而与之对应的可变性自然就是可以改变。下面通过两个具体的实例,String和StringBuilder来具体理解这两个概念。
String是不可变数据类型,而StringBuilder是可变数据类型。
定义了一个String变量赋值为“a”,即可看做拿出了一个盒子,放入了代表a的小球,现在我们要改变变量值为“ab”,我们没办法直接改变变量的值,而是改变变量指向的空间,即我们又拿出了一个新的盒子,并在盒子里放入了代表a和b的小球。所以对String来说,它是可变的引用不可变的数据类型,对此可以通过改变引用来指向不同的值。
而对StringBuilder,我们定义了该类型变量并赋值为"a",即拿出了一个盒子放入了代表a的小球,现在改变变量值为“ab”,我们只需要改变该空间内的值即可,即在原本的盒子里放入代表a和b的小球,原本的小球抛弃即可。所以StringBuilder是不可变的引用可变的数据类型,可以直接改变指向的值。
通过定义变量时标注final声明不可变的引用。当我们想使得某个引用不可变时,可以使用这个方法,静态检查会检查该变量的引用是否发生了改变。
对于可变与不可变来说,使用可变的数据类型可以实现共享数据,使得程序获得更好地性能。而不可变数据类型相对可变数据类型来说则更加的安全,可以避免可变数据类型引发一些难以发现的错误。
总结
要熟练地掌握数据与引用的可变与不可变,对于其各自应用的范围和优缺点都进行的了解,在编程时也要额外注意可变类型的数据在无意中可能会引发的错误,以免带来难以预料的后果。