NumberFormat不会因2个小数分隔符而崩溃

时间:2017-03-03 17:03:50

标签: java number-formatting

我对NumberFormat

的行为有疑问

当我想将格式化的String翻译/解析为Number时,我想使用NumberFormat,因为它为千位和小数分隔符提供了很好的预设。此外,如果提供的String不是有效Number,我希望它崩溃。

一个例子:

// works as expected
String testInput1 = "3,1415";
NumberFormat germanNumberFormat = NumberFormat.getInstance(Locale.GERMANY);
Number number1 = germanNumberFormat.parse(testInput1);
System.out.println(number1); // prints 3.1415

// does not work as expected, cuts off the number after the 2nd decimal
// separator, expected it to crash with java.lang.NumberFormatException:
// multiple points
String testInput2 = "3,14,15";
Number number2 = germanNumberFormat.parse(testInput2);
System.out.println(number2); // prints 3.14

我目前使用Double.parseDouble(String s)来执行此附加操作:

// crashes with java.lang.NumberFormatException: multiple points
double number2WithError = Double.parseDouble(testInput2.replace(",", "."));

我是否可以使用NumberFormat来获得我所需的/预期的行为,除了编写我自己的包装类之外,还可以对其进行一些额外的检查。多个小数分隔符?

另外,我知道parse(String source)使用的NumberFormat方法的JavaDoc说:

  

从给定字符串的开头解析文本以生成数字。该方法可能不使用给定字符串的整个文本。   

  有关数字解析的更多信息,请参阅{@link #parse(String,ParsePosition)}方法。

parse(String source, ParsePosition parsePosition)

  

如果可能,返回Long(例如,在[Long.MIN_VALUE,Long.MAX_VALUE]并且没有小数的范围内),否则返回Double。如果设置了IntegerOnly,将停止在小数点(或等效;例如,对于有理数" 1 2/3",将在1之后停止)。不抛出异常;如果没有对象可以解析,索引就不变了!

这并不能告诉我为什么这个方法会这样做。我从这些中获得的是,他们只能解析String的部分内容(他们显然在这里做了什么),并且可能只是在开始时(起始位置)开始解析,直到找到他们无法处理的内容为止。

我没有找到涉及此问题的现有问题,所以如果已有问题,请随时关闭此帖子,并链接到该帖子。

1 个答案:

答案 0 :(得分:1)

NumberFormat.parse(String)表现得非常as documented

  

从给定字符串的开头解析文本以生成数字。 该方法可能不会使用给定字符串的整个文本。

(强调补充)

你问:

  

我是否可以使用NumberFormat来获得我所需的/预期的行为,除了编写我自己的包装类之外,还可以对其进行一些额外的检查。多个小数分隔符?

你不能提供一种格式,使NumberFormat.parse()只输入一个可以根据格式解析的初始子字符串的输入异常。但是,可以使用NumberFormat.parse(String, ParsePosition)来确定是否解析了整个输入,因为解析位置参数不仅用于指示方法从哪里开始,还用于方法说它停在哪里。这比实现格式特定的额外检查要好得多。例如:

ParsePosition position = new ParsePosition(0);
Number result = format.parse(input, position);

if (position.getIndex() != input.length()) {
    throw new MyException();
}

另外,你写道:

  

这并没有告诉我为什么这个方法会这样做。

它的行为方式是因为有时解析输入的初始部分正是您想要做的。如图所示,您可以在更轻松的解析之上构建更严格的解析,但是以相反的方式执行它会更加困难。