首页 » 编写高质量代码:改善Java程序的151个建议 » 编写高质量代码:改善Java程序的151个建议全文在线阅读

《编写高质量代码:改善Java程序的151个建议》建议23:不要让类型默默转换

关灯直达底部

我们出一个小学生的题目给大家做做看,光速是每秒30万公里,根据光线旅行的时间,计算月亮与地球、太阳与地球之间的距离。代码如下:


public class Client{

//光速是30万公里/秒,常量

public static final int LIGHT_SPEED=30*10000*1000;

public static void main(Stringargs){

System.out.println("题目1:月亮光照射到地球需要1秒,计算月亮和地球的距离。");

long dis1=LIGHT_SPEED*1;

System.out.println("月亮与地球的距离是:"+dis1+"米");

System.out.println("--------------------------------------------");

System.out.println("题目2:太阳光照射到地球上需要8分钟,计算太阳到地球的距离。");

//可能要超出整数范围,使用long型

long dis2=LIGHT_SPEED*60*8;

System.out.println("太阳与地球的距离是:"+dis2+"米");

}

}


估计你要鄙视了,这种小学生乘法计算有什么可做的。不错,确实就是一个乘法运算,我们运行一下看看结果:


题目1:月亮光照射到地球需要1秒,计算月亮和地球的距离。

月亮与地球的距离是:300000000米

--------------------------------------------

题目2:太阳光照射到地球上需要8分钟,计算太阳到地球的距离。

太阳与地球的距离是:-2028888064米


太阳和地球的距离竟然是负的,诡异。dis2不是已经考虑到int类型可能越界的问题,并使用了long型吗,为什么还会出现负值呢?

那是因为Java是先运算然后再进行类型转换的,具体地说就是因为disc2的三个运算参数都是int类型,三者相乘的结果虽然也是int类型,但是已经超过了int的最大值,所以其值就是负值了(为什么是负值?因为过界了就会从头开始),再转换成long型,结果还是负值。

问题知道了,解决起来也很简单,只要加个小小的"L"即可,代码如下:


long dis2=LIGHT_SPEED*60L*8;


60L是一个长整型,乘出来的结果也是一个长整型(此乃Java的基本转换规则,向数据范围大的方向转换,也就是加宽类型),在还没有超过int类型的范围时就已经转换为long型了,彻底解决了越界问题。在实际开发中,更通用的做法是主动声明式类型转化(注意不是强制类型转换),代码如下:


long dis2=1L*LIGHT_SPEED*60*8;


既然期望的结果是long型,那就让第一个参与运算的参数也是long型(1L)吧,也就是明说“嗨,我已经是长整型了,你们都跟着我一起转为长整型吧”。

注意 基本类型转换时,使用主动声明方式减少不必要的Bug。