数据类型与类型检查
- 数据类型
- 静态/动态类型检查
-
- 静态类型检查
-
- 原理
- 种类
- 动态类型检查
-
- 种类
- 两者关系
- 可变/不变的数据类型
-
- 不变的数据类型
-
- final
- String
- 特点
- 可变的数据类型
-
- StringBuilder
- 特点
- 解决可变类型不安全的方法
- Snapshot理解数据类型
数据类型
基本数据类型/对象数据类型
静态/动态类型检查
静态类型检查
原理
可在编译阶段发现错误,避免了将错误带入到运行阶段,可提高程序正确性/健壮性。
Java是静态类型语言,所有变量的类型在编译时(在程序运行之前)都是已知的,因此编译器也可以推导出所有表达式的类型。如果a和b被声明为int型,那么编译器得出a+b也是int型。
比如,如果输入"a"*“b”,尝试将两个字符串相乘,然后静态类型检查将在编程时捕获此错误,而不是在执行期间等待到达该行。
种类
1.Syntax errors 语法错误
2.Wrong names 类名/ 函数名错误:比如Math.sine(2),正确的名字是sin
3.Wrong number of arguments 参数数目错误,比如Math.sin(30, 20) .
4.Wrong argument types 参数类型错误, like Math.sin(“30”) .
5.Wrong return types 返回值类型错误, like return “30”,但是这个函数应该返回int
动态类型检查
种类
1.Illegal argument values 非法的参数值:例如,整数表达式x/y只有在y实际上为零时才错误;否则它的工作原理。在这个表达式中,除以0不是静态误差,而是动态误差。
2.Unrepresentable return values 非法的返回值:当特定的返回值不能在类型中表示时。
3.Out-of-range indexes 越界:在字符串上使用负数或太大的索引。
4.Calling a method on a null object reference. 空指针
两者关系
静态检查倾向于与变量的特定值无关的类型和错误有关。静态类型保证一个变量会有这个集合中的一些值,但是我们直到运行时才知道它的确切值。因此,如果错误只会由某些值引起,如除0或索引超出范围,那么编译器不会引发关于它的静态错误。
相比之下,动态检查往往是关于特定值引起的错误。
静态检查:关于“类型”的检查,不考虑值
动态检查:关于“值”的检查
可变/不变的数据类型
改变一个变量:将该变量指向另一个值的存储空间
改变一个变量的值:将该变量当前指向的值的存储空间中写入一个新的值。
不变的数据类型
不变对象:一旦被创建,始终指向同一个值/引用
如果是引用类型,也可以是不变的:一旦确定其指向的对象,不能再被改变
final
final int a = 5;
1.final类无法派生子类
2.final变量无法改变值/引用
3.final方法无法被子类重写
String
特点
缺点:使用不可变类型,对其频繁修改会产生大量的临时拷贝( 需要垃圾回收)
优点:安全
可变的数据类型
可变对象:拥有方法可以修改自己的值/引用
StringBuilder
特点
优点:可变类型最少化拷贝以提高效率
缺点:不安全
比如
public static int sum(List<Integer> list) {
int sum = 0;
for(int x: list) {
sum += x;
}
return sum;
}
public static int sumAbsolute(List<Integer> list) {
for(int i = 0; i < list.size(); i++) {
list.set(i, Math.abs(list.get(i)));
}
return sum(list);
}
public static void main(String[] args) {
List<Integer> myData = Arrays.asList(-5, -3, -2);
System.out.println(sumAbsolute(myData));
System.out.println(sum(myData));
}
最后输出结果为
10
10
因为可变类型导致list的值发生变化
解决可变类型不安全的方法
进行防御式拷贝
Snapshot理解数据类型
基本类型
对象类型
对象值是一个按其类型标记的圆。
可变对象
不可变对象:用双线椭圆
String s = “a”;
s = s + “b”;
不可变的引用:用双线箭头