数据类型与类型检验(1)

程序设计语言中的数据类型

类型和变量:

类型是一组值,以及可以对这些值执行的操作。数据类型:一组值以及可以对其执行的操作
示例:
–布尔值:真值(真或假)。
–int:整数(0,1,-47)。
–double:实数(3.14,1.0,-2.1)。
–字符串:文本(“你好”、“示例”)。
变量:存储特定类型值的命名位置
–形式:类型名称;
–示例:字符串foo
变量:用特定数据类型定义,可存储满足类型约束的值Java有几种基本类型基本数据类型,例如:
–int(对于5和-200这样的整数,但限于2^31范围,或者
大约20亿)
–long(适用于2^63以上的较大整数)
–布尔值(真或假)
–double(对于代表实数子集的浮点数
数字)
–char(对于像“A”和“$”这样的单个字符)
Java也有对象类型对象数据类型,例如:
–字符串表示一系列字符。
–BigInteger表示任意大小的整数。
按照Java惯例,基本类型是小写的,而对象类型以大写字母开头。

对象类型形成层次结构:

根是对象(所有非基元都是对象)
–除对象之外的所有类都有一个父类,用扩展子句指定
class Guitar extends Instrument { … }
如果省略扩展子句,默认为对象
一个类是其所有超类的实例(继承关系)
–从其超类继承可见字段和方法
–可以覆盖方法以改变它们的行为
在这里插入图片描述

包装基本类型

将基本类型包装为对象类型
通常是在定义容器类型的时候使用它们(容器类型操作的元素要求是
对象类型,所以需要对基本数据类型进行包装,转换为对象类型)
一般情况下,尽量避免使用(会降低性能)
一般可以自动转换
例:在这里插入图片描述

操作符

操作符:执行简单计算的符号操作符
–赋值:=
–加法:+
–减法:-
–乘法:*
–除法:/
操作顺序:遵循标准数学规则
– 1.圆括号
– 2.乘法和除法
– 3.加法和减法
字符串串联(+)
–String text = " hello “+” world ";
–text = text+“number”+5;// text = “hello world number 5”
操作是接受输入并产生输出的函数(有时会改变值本身)。
–作为中缀、前缀或后缀运算符。例如,a + b调用操作+ : int × int → int。
–作为对象的方法。例如,bigint1.add(bigint2)调用操作add:big integer×big integer→big integer。
–作为一项功能。例如,Math.sin(theta)将操作sin称为:double → double。在这里,数学不是一个对象。它是包含sin函数的类。

静态与动态数据类型检查

Java是一种静态类型的语言。
–所有变量的类型在编译时(在程序运行之前)都是已知的,因此编译器也可以推导出所有表达式的类型。
–如果a和b被声明为int,那么编译器会得出a+b也是int的结论。
–实际上,Eclipse环境在您编写代码的时候就这样做了,所以当您还在打字的时候,就会发现很多错误。
– 在编译阶段进行类型检查
在像Python这样的动态类型语言中,这种检查被推迟到运行时(当程序运行时)。
语言可以提供的三种自动检查:
–静态检查:甚至在程序运行之前就自动发现了错误。
–动态检查:执行代码时会自动发现错误。
–不检查:语言根本不能帮助你找到错误。你必须自己小心,否则最终会得到错误的答案。
不用说,静态捕捉一个bug比动态捕捉它好,动态捕捉它比根本不捕捉它好。静态检查 >> 动态动态 >> 无检查

静态检查

静态检查意味着在编译时检查错误。

  • bug是程序的毒药。
    静态类型防止一大类bugs感染您的程序:准确地说,是对错误类型的参数应用操作导致的bugs。
    如果你写了一行不完整的代码,比如:“5”*“6”
    试图将两个字符串相乘,那么静态类型将在您仍在编程时捕获此错误,而不是等到执行期间到达该行
  • 动态类型检查的语言也会进行静态检查(除了类型外的其他语法错误)
    类名/函数名错误,就像Math.sine(2) .(右边
    名字是sin)
  • 参数数目错误,比如Math.sin(30,20)。
  • 参数类型错误,比如Math . sin(“30”)。
  • 返回值类型错误,比如从声明返回int的函数中返回“30”。

动态检查

  • 非法的参数值。例如,整数表达式x/y只有在y实际为零时才是错误的;否则它会起作用。所以在这个表达式中,被零除不是静态误差,而是动态误差。
  • 非法的返回值,即当特定返回值无法在类型中表示时。
  • 越界,例如,对字符串使用负的或太大的索引。
  • 空指针

静态检查倾向于类型,与变量的具体值无关的错误。
–静态类型保证一个变量将从该集合中获得一些值,但是我们直到运行时才知道它到底有哪个值。
–因此,如果错误仅由某些值引起,如被零除或索引超出范围,那么编译器不会引发静态错误。
相比之下,动态检查倾向于特定值引起的错误

基本类型不是真数字

Java和许多其他编程语言中的一个陷阱是,它的原始数值类型有特例不像我们习惯的整数和实数。
因此,一些真正应该动态检查的错误根本没有检查。
–整数除法:5/2不返回分数,它返回截断的整数。
–整数溢出。如果计算结果太正或太负而不适合那个有限的范围,它会悄悄地溢出并返回一个错误的答案。(无静态/动态检查!)例如,int big = 200000 * 200000
–浮点类型中的特殊值。NaN(“不是数字”)、POSITIVE_INFINITY, and NEGATIVE_INFINITY.(正无穷大和负无穷大)

  • Int a = resulOfFunction(XX);//例如,-9
  • Math.sqrt(a)的结果是NaN,不是动态错误!

例:在这里插入图片描述

改变变量或变量值

改变一个变量、改变一个变量的值,二者有何区别?
改变一个变量:将该变量指向另一个存储空间
改变一个变量的值:将该变量当前指向的存储空间中写入一个新的值。

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

不变性

不变性:重要设计原则
不变数据类型:一旦被创建,其值不能改变
如果是引用类型,也可以是不变的:一旦确定其指向的对象,不能再被改变指向其他对象

  • 要使引用不可变,请用关键字final声明它
    final int n = 5;
    final Person a = new Person(“Ross”);

编译器进行静态类型检查时,如判断final变量首次赋值后发生了改
变,会提示错误。
尽量使用final变量作为方法的输入参数、作为局部变量。
final表明了程序员的一种“设计决策”
提示:
final类无法派生子类
final变量无法改变值/引用
final方法无法被子类重写

可变性与不可变性

不变对象:一旦被创建,始终指向同一个值/引用
可变对象:拥有方法可以修改自己的值/引用
String是不可变类型的一个例子。
String对象总是代表相同的字符串。
由于String是不可变的,一旦创建,String对象总是具有相同的值。
要在String末尾添加内容,您必须创建一个新的String对象:
在这里插入图片描述
StringBuilder是可变类型的一个例子。
它有删除部分字符串、插入或替换字符等方法。
这个类有改变对象值的方法,而不仅仅是返回新值:
在这里插入图片描述
所以二者有区别吗?最终的值都是一样的
当只有一个引用指向该对象,二者没有区别
但是当有多个引用的时候,差异就出现了
当另一个变量t指向与s相同的String对象,而另一个变量tb指向与sb相同的StringBuilder时,不可变对象和可变对象之间的差异就变得更加明显
在这里插入图片描述
使用不可变类型,对其频繁修改会产生大量的临时拷贝(需要垃圾回收)
–在构建最终字符串的过程中,第一个数字(“0”)实际上被复制了n次,第二个数字被复制了n-1次,以此类推。
–实际上,即使我们只连接了n个元素,复制这些数据也要花费O(n2)个时间。
StringBuilder旨在最大限度地减少这种复制。可变类型最少化拷贝以提高效率
–它使用简单但巧妙的内部数据结构来避免任何复制,直到最后,当您使用toString()调用请求最终字符串时。
所以
使用可变数据类型,可获得更好的性能
也适合于在多个模块之间共享数据
既然如此,为何还要用不可变类型?
不可变类型更“安全”,在其他质量指标上表现更好
可变性使得难以理解程序正在做什么,更难满足方法的规约
折中,看你看重哪个质量指标

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值