`

一个“诡异”的NumberFormatException

 
阅读更多

前几天线上一个功能莫名其妙没有正常执行,而且奇怪的这个功能模块以及很久没有改动了,而且一直运行的好好的,从没出问题,今天排查看日志,发现是程序在进行一段内存排序时,抛NumberFormatException了。

Exception in thread "main" java.lang.NumberFormatException: For input string: "30d"

 

这我就纠结了,因为内存排序是通过把从数据库去取出来的String转化成BigDecimal来进行排序的,而且NumberFormatException就是抛在这句代码上:

 

		BigDecimal bg = new BigDecimal(answer);

 因为answer是从DB里取出来的,这个answer是用户通过页面提交的,而且在存到DB之前,一个同事专门写了个方法来判断用户提交的答案是不是能转换成数字,如果不能转换成数字,则会拒绝用户的这次提交。既然已经过滤掉了非法的答案,那为什么还会把30d存入到DB呢?

因此,我去看过滤掉非法答案的非法是如何来过滤的?

		try{
			Float floatAnswer = Float.valueOf(answer);
		}catch (NumberFormatException e) {
			// TODO: handle exception
		}

  如果上述代码没有抛出异常,就认为输入的答案在格式上时合法的。一看到这个Float.valueOf(answer),我就知道问题是出在这里了, Float.valueOf(answer)和new BigDecimal(answer)在判断是一个string能否正确转换成数字上采取的是不同的标准,先来看一下Float.value(String s)方法:

 

    public static Float valueOf(String s) throws NumberFormatException {
	return new Float(FloatingDecimal.readJavaFormatString(s).floatValue());
    }

 

  FloatingDecimal.readJavaFormatString(s)方法是sun.misc.FloatingDecimal里面,这个类下载open jdk的源码后可以看到,通过截取readJavaFormatString方法的一段代码就可以知道为什么30d这个数字会通过校验被存进DB了

if ( i < l &&
    ((i != l - 1) ||
    (in.charAt(i) != 'f' &&
     in.charAt(i) != 'F' &&
     in.charAt(i) != 'd' &&
     in.charAt(i) != 'D'))) {
    break parseNumber; // go throw exception

  上述代码段可以看出,数字后面加上字母D、d、F、f是合法的。

而BigDecimal(String val)在进行校验的时候,则不允许字母出现在最后,但这样的字符串"2e9"是合法的,因为可以理解成科学计算法,因为代码过长,所以就不具体分析了。

至此,这个诡异的NumberFormatException已经分析清楚了,虽然问题的原因已经弄清楚了,但我认为从这个问题中可以总结出两点:

1.对于一些常用API方法,需要彻底弄清出原理,如果实在不清楚其具体原理,也需要用一些边界值去测试

2.对于任何参数,如果该参数使用的时候存在某种风险,那都要采取怀疑态度,不要因为某些地方已经对这个参数做过校验了就完全相信(就像上面的例子里的情况)

 

一点小总结,

分享到:
评论
1 楼 1234abc 2016-03-20  
谢谢分享,很好的实例,赞一个

相关推荐

    java.lang.NumberFormatException For inputstring 4294967295处理方法

    java.lang.NumberFormatException For inputstring 4294967295处理方法

    详解java.lang.NumberFormatException错误及解决办法

    主要介绍了详解java.lang.NumberFormatException错误及解决办法,本文详解的介绍了错误的解决方法,感兴趣的可以一起来了解一下

    java加减乘除计算器界面编程

    编写一个应用程序,设计一个标题为“计算”的窗口,设计四个按钮,分别命名为“加”、“减”、“积”、“除”,设计三个文本框,单击相应的按钮,将两个文本框的数字做运算,在第三个文本框中显示结果。要求能够处理...

    java 数字格式转换异常(NumberFornatException)

    java 数字格式转换异常(NumberFornatException) java 数字格式转换异常(NumberFornatException)

    android集成文字输入,语音输入,表情输入自定义view

    这是一个已经集成了聊天发送文字表情和语音功能的输入模块 无需再写任何代码 自己写的 5分绝对值 使用方法: 第一步:文件怎么放 把三个文件夹里的东西分别放在制定的地方就行 第二步:布局到我的activity中 ...

    重载与覆写/重写的区别

    简单说,就是同样的一个方法能够根据输入数据的不同,做出不同的处理,  即方法的重载——有不同的参数列表(静态多态性)  而当子类继承自父类的相同方法,输入数据一样,但要做出有别于父类的响应时,你就要...

    dbswitch工具提供源端数据库向目的端数据库的批量迁移同步功能,支持数据的全量和增量方式同步

    dbswitch工具提供源端数据库向目的端数据库的批量迁移同步功能,支持数据的全量和增量方式同步。包括:结构迁移:支持字段类型、主键信息、建表语句等的转换,并生成建表SQL语句。支持基于正则表达式转换的表名与...

    单片机点阵毕业设计

    本文介绍一种基于PIC16F877A[5]单片机控制系统,设计了16×48小型的LED点阵屏。此设计采用动态扫描方式,通过单片机控制3-8译码器74LS138和数据移位寄存器74HC595来驱动显示屏的显示,此方案实用简单,软件编程方便...

    java-bbs项目,ssh

    java-bbs项目,ssh

    JAVA.2核心技术.卷II.高级特性7th.part08.rar

    JAVA.2核心技术.卷II.高级特性7th.part08.rar

    java 异常总结

    其他还有很多异常,我就不一一列举了,我要说明的是,一个合格的程序员,需要对程序中常见的问题有相当的了解和相应的解决办法,否则仅仅停留在写程序而不会改程序的话,会极大影响到自己的开发的。关于异常的全部...

    java实验2实验报告.doc

    编写一个四则运算程序,要求用户输入一个x值和一个y值,以及一个四则运算符。如 果用户输入正确,则给出运算结果,如果输入错误,则给出出错警告。(利用异常处理 编程,尽量使用java现成的异常类,如没有可自定义...

    基于JSP技术的银行管理系统的毕业设计与实现.doc

    27 5.2 NumberFormatException异常 27 5.3 404错误页 28 5.4 乱码显示的处理 28 6 结论 29 参考文献 30 致 谢 31 基于JSP技术的银行管理系统的设计与实现 摘 要:本文具体讲述了如何使用JSP技术建立一个银行管理系统...

    android异常类型和处理

    NullPointException 传说中的空指针异常,如果一个对象不存在,你有对这个对象使用点操作,那么就会出现该异常 NumberFormatException 把字符串转成数字失败时出现的数字格式异常 AssertionError 断言错误 ...

    标准体重计算器.rar

    自己写的,需要的童鞋可以下来看看 ... } catch (NumberFormatException e) { jieguo.setText("你以为我真的是神仙吗?你什么都不告诉我,我怎么给你测啊!!!"); jieguo.setTextColor(0xffFF0033); return; }

    Wk3Lab3_Operations

    编写程序运算符,该运算符从命令行读取一个运算和两个整数,然后对数字进行运算并打印出结果。 例如,命令行: java运算符加7 9 7 + 9 = 16 实现加减运算。 如果输入了未知操作或非整数,则程序应打印错误消息。 ...

    最全java考试编程题

    *555555555*)(3)实现至少一处自定义 Exception(4)进行 Exception 控制 public class Triangle { public static void main(String[] args) { try { int height = Integer.parseInt(args[0]); // 从命令行参数读取...

    JAVA简单异常处理(main方法中的args[]命令行参数传入两个操作数)

    编写程序,使用main方法中的args[]命令行参数传入两个操作数,进行除法运算, 要求对NumberFormatException类型的异常进行处理,并且自定义异常类OnlyOneOprandException与NoOprandException,并对之进行处理。

    停车场管理系统(java).docx

    public class Method { private int intinput() throws IOException,NumberFormatException { BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); String str=br.readLine(); int i=Integer...

Global site tag (gtag.js) - Google Analytics