`

一个“诡异”的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编程中,`java.lang.NumberFormatException`是一个常见的运行时异常,它通常发生在尝试将一个字符串转换为数值类型(如int、long、float或double)时,但该字符串无法被解析为有效的数值。"For input string: ...

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

    Java.lang.NumberFormatException错误是Java中的一种常见异常,主要是因为将非数字类型的数据强制转换为数字类型时引发的。例如,将String类型的数据强制转换为Integer类型时,如果该String类型的数据不符合数字格式...

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

    在Java编程语言中,`NumberFormatException`是一个常见的运行时异常,它发生在尝试将字符串转换为特定数字类型(如`Integer`, `Double`, `Float`等)时,如果字符串不能被解析为对应类型的数值,就会抛出这个异常。...

    [JAVA]二进制字符串转十进制带异常抛出

    在上述代码中,我们尝试用`parseInt()`方法转换字符串,如果失败,则捕获`NumberFormatException`并抛出一个自定义的`IllegalArgumentException`,附带有关于问题的详细信息。 然而,我们还需要考虑另一种异常情况...

    用java语言写的实现输入整数

    然而,如果用户输入的不是一个有效的整数,`parseInt`方法会抛出一个`NumberFormatException`。因此,我们使用`try-catch`块来处理这个可能的异常。当捕获到`NumberFormatException`时,我们会打印一条错误信息,...

    用NETBEAN 6.8 做一个计算器的代码

    在.NET编程环境中,NetBeans 6.8是一个流行的开源集成开发环境(IDE),它支持多种语言,包括Java、C++和Groovy等。利用NetBeans 6.8创建一个计算器项目是一个很好的学习实践,可以让你熟悉GUI编程和事件处理。下面...

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

    在Java编程中,创建一个图形用户界面(GUI)计算器是一个常见的练习,可以帮助初学者理解事件处理和异常处理的概念。在这个“java加减乘除计算器界面编程”项目中,我们需要实现一个简单的计算器应用,具备加、减、...

    j2me猜数字游戏(猜一个随机数)

    开发者会创建一个`Random`对象,然后调用其`nextInt(int bound)`方法生成一个指定范围内的随机整数。例如,如果设定范围为1到100,代码可能如下: ```java Random rand = new Random(); int secretNumber = ...

    判断一个字符串或字符串中的一个字符是否为数字类型

    在编程领域,判断一个字符串或字符串中的一个字符是否为数字类型是常见的操作,尤其是在处理用户输入、数据分析或者格式验证时。下面将详细讲解几种不同语言中实现这一功能的方法,以及如何确保判断的安全性和效率。...

    Java程序将字符串转换为Long.docx

    在Java编程语言中,将字符串转换为Long类型的值是一个常见的操作。这通常涉及到解析字符串,将其内容解释为数值。以下是一些将字符串转换为Long的方法: 1. **使用Long.parseLong()方法** `Long.parseLong()` 方法...

    实验 7异常处理.zip

    )是一个简单的命令行计 算器。注意,如果某个操作数是非数值的,程序就会中止。编写一个程序,利用异常处 理器来处理非数值操作数; 然后编写另一个不使用异常处理器的程序,达到相同的目的。 程序在退出之前应该显示...

    java源码:java求一个整数的因子.zip

    在Java编程语言中,求解一个整数的因子是一个常见的问题,这通常涉及到数学和算法的知识。本项目提供的源码就是一个解决这个问题的例子。下面将详细解释这个过程,并深入探讨相关知识点。 1. **整数因子的基本概念*...

    JAVA闰年判断程序

    JOptionPane.showInputDialog方法用于弹出一个输入对话框,用户可以在其中输入一个数字年份。JOptionPane.showMessageDialog方法用于弹出一个消息对话框,显示判断结果。 在main方法中,我们首先使用JOptionPane....

    android简单乘法计算器

    在Android平台上开发一个简单的乘法计算器涉及到多个技术层面,包括用户界面设计、事件处理、运算逻辑以及Android应用程序的基础架构。下面我们将深入探讨这些关键知识点。 首先,`Android`是Google开发的一款开源...

    停车场管理系统

    停车场管理系统是一个典型的计算机应用系统,旨在管理停车场的停车信息。该系统由多个类组成,每个类都有其特定的功能。 首先,我们来看一下`Method`类。该类提供了多种输入方法,包括整数输入、字符串输入、判断...

    src04 Byte

    在Java编程语言中,`java.lang.Byte` 类用于封装一个基本类型的 `byte` 值。该类不仅提供了将 `byte` 转换为 `String` 和从 `String` 转换为 `byte` 的方法,还提供了一些常量和其他在处理 `byte` 类型数据时非常...

    java中string和int型的相互转换.doc

    如果字符串不能被正确地转换为 int 类型,同样也会抛出一个 `NumberFormatException`。 int 转换为 String 在 Java 中,将 int 类型转换为 String 类型可以使用三种方法: 1. 使用 `String.valueOf()` 方法 ```...

    java\String类型转换成整数double

    同样地,如果字符串无法解析为一个整数,则会抛出`NumberFormatException`。 示例代码: ```java String strInt = "123"; try { int i = Integer.parseInt(strInt); System.out.println(i); // 输出:123 } catch...

    编程语言Java经典算法.pdf

    Java Swing库被用来创建一个简单的用户界面,它通过JOptionPane.showInputDialog()弹出一个对话框让用户输入一个字符串,然后程序会将这个字符串解析成整数,并执行其他操作。 7. 条件运算符(Ternary Operator)...

    tradukisto,创建一个将数字转换为单词表示的Java库。.zip

    【标题】"Tradukisto: 创建一个将数字转换为单词表示的Java库" 【描述】"Trudukisto是一个基于Java 8的开源项目,它的主要功能是将阿拉伯数字转换成对应的英文单词形式,这对于开发那些需要以口语化方式显示数字的...

Global site tag (gtag.js) - Google Analytics