`
fcmfcm01
  • 浏览: 65782 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

BigDecimal在1.5编译时的错误

阅读更多

今天在写程序的时候发现了一个问题,公司的代码是基于JDK1.4的,因为找不到1.4的JDK,我只能使用ant,通过设定source level的办法来控制编译结果:

<javac encoding="UTF-8"  destdir="${dir.ext}/${dir.classes}" target="${javac.target.version}" classpathref="lib.class.path" deprecation="false" debug="${javac.debug}" optimize="${javac.optimize}" failonerror="true" source="1.4">

 

结果编译好的代码在1.5下边没法运行,出现下边的错误:

java.lang.NoSuchMethodError: java.math.BigDecimal.<init>(I)V

 

找到代码,看到BigDecimal对象的定义如下:

new BigDecimal(1);

 

再查看了一下API手册,发现

BigDecimal
public BigDecimal(int val)将 int 转换为 BigDecimal。BigDecimal 的标度为零。 

参数:
val - 要转换为 BigDecimal 的 int 值。
从以下版本开始: 
1.5 

 

public BigDecimal(double val)将 double 转换为 BigDecimal,后者是 double 的二进制浮点值准确的十进制表示形式。返回的 BigDecimal 的标度是使 (10scale × val) 为整数的最小值。 
注: 

此构造方法的结果有一定的不可预知性。有人可能认为在 Java 中写入 new BigDecimal(0.1) 所创建的 BigDecimal 正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于 0.1000000000000000055511151231257827021181583404541015625。这是因为 0.1 无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。这样,传入 到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。 
另一方面,String 构造方法是完全可预知的:写入 new BigDecimal("0.1") 将创建一个 BigDecimal,它正好 等于预期的 0.1。因此,比较而言,通常建议优先使用 String 构造方法。 
当 double 必须用作 BigDecimal 的源时,请注意,此构造方法提供了一个准确转换;它不提供与以下操作相同的结果:先使用 Double.toString(double) 方法,然后使用 BigDecimal(String) 构造方法,将 double 转换为 String。要获取该结果,请使用 static valueOf(double) 方法。 

参数:
val - 要转换为 BigDecimal 的 double 值。 
抛出: 
NumberFormatException - 如果 val 为无穷大或 NaN。

 

猜想是不是编译的时候1.5优先把适合于自己的构造函数作为默认构造函数了,试了一下把BigDecimal对象的定义换为

new BigDecimal(1.0);

 

再运行,OK。BUG解决。

 

原因分析:在Java的内置类型的默认定义中,Int 型数据一般初始化为 1,2 ,3这种形式,而double型数据一般初始化为1.0,2.0,3.0这样的形式。因为在1.4的时候,API中不存在BigDecimal(int val) 这样的构造函数,JDK在编译的时候会在后台偷偷的将int型数据提升为double型数据,而在1.5的JDK中,由于已经存在BigDecimal(int val)这样的构造函数,编译器就会直接将Int型数据作为默认数据输入,进而造成了先前的找不到构造函数的错误。

 

 

PS:这个不知道算不算是JDK的一个bug? 用高版本的JDK编译低版本的Java代码的人估计还不少。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics