错误数据类型导致的风险
我们用一个案例来说明:定义的数据类型如果不合理,可能导致的风险。
在“定义和使用一个方法”一节,我们使用int
来定义用户的资产总额(balance
)和新增投资金额(newInvest
),然而,int
类型存在一个问题:它最大只能表示大约20亿的整数(最小只能表示大约负20亿的整数)。如果一个客户的账户余额高于20亿将如何?
一般情况下,如果我们想直接给int类型的变量赋一个大于约20亿的值,现代开发工具和编译器可以发现并直接报错,比如我们写
int balance = 3000000000; //30亿
编译器会报错,提示你给一个int变量赋的值超出了其能表达的范围。
The literal 3000000000 of type int is out of range InvestmentManager.java /cs_course/src/methoddefinition line 5 Java Problem
但是,依赖编译器来检查所有错误是不可靠的,特别是潜在的业务逻辑错误而非语法错误,编译器是无法识别的。比如,如下代码,表示来追加投资的人账户上本来有20亿,现在他要追加投资10亿,我们看会发生什么。
代码
package methoddefinition;
public class InvestmentManager {
public static void main(String[] args) {
// TODO Auto-generated method stub
int balance = 2000000000;
int newInvest = 1000000000;
System.out.println("Deposit succeeds. Your current balance is " + deposit(newInvest, balance));
}
static int deposit(int newInvest, int balance){
return balance + newInvest;
}
}
系统不会报错,甚至不会有任何警告!其中20亿和10亿的数据可以是从数据库或者柜台输入的。那么运行上述代码,系统会输出:
Deposit succeeds. Your current balance is -1294967296
客户的30亿变成了负的12.95亿元!如果你将这个数据直接写入客户的账户,那么吃上官司是不可避免的了。
问题:此处的问题就是int
无法表示超过大约20亿的整数,因此此处我们需要用长整数long
,我们将输入和输出的数据类型都修改为long
:
package methoddefinition;
public class InvestmentManager {
public static void main(String[] args) {
// 这里等号右边是个int(因为没加L),java在赋值的时候,自动转换成了long。
// 如果数值超过约2100000000,就必须加L,不然会报错。
long balance = 2000000000;
long newInvest = 1000000000;
System.out.println("Deposit succeeds. Your current balance is " + deposit(newInvest, balance));
}
static long deposit(long newInvest, long balance){
return balance + newInvest;
}
}
Tips
- 上面的代码因为
deposit
方法输入和输出都换成long
了,所以,返回类型,和参数列表里数据的类型都要修改为long
;- 在main函数里,定义两个要用的变量也要用
long
,想想为什么呢?
再运行我们可以得到正确的结果
Deposit succeeds. Your current balance is 3000000000
long
最大可以表示大约9千亿亿的整数,想必需要用到这么大整数的场景非常少,但是我们在定义数据类型的时候仍然需要当心。
此外,资金数额可能出现小数,所以此处我们用浮点数类型更合理,双精度浮点数类型
double
是最佳选择,因为float
类型最多有8位有效数字,如果一个客户的账户余额超过一百万,比如1234567890.99f
末尾的钱数会被抹去,存在数据库里的数字将变成123456794.f
那样你又可能惹上官司。(9是四舍五入得到的,后面的4是无效的)