NumberFormat 不会因 2 个小数分隔符而崩溃
Posted
技术标签:
【中文标题】NumberFormat 不会因 2 个小数分隔符而崩溃【英文标题】:NumberFormat doesn't crash with 2 decimal separators 【发布时间】:2017-03-03 17:03:49 【问题描述】:我对@987654321@ 的行为有疑问:
当我想将格式化的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)
方法的JavaDoc 说:
从给定字符串的开头解析文本以生成一个数字。该方法可能不会使用给定字符串的整个文本。
有关数字解析的更多信息,请参阅 @link #parse(String, ParsePosition) 方法。
和parse(String source, ParsePosition parsePosition)
:
如果可能,则返回 Long(例如,在 [Long.MIN_VALUE, Long.MAX_VALUE] 范围内且不带小数),否则返回 Double。如果设置了 IntegerOnly,将在小数点处停止(或等效项;例如,对于有理数“1 2/3”,将在 1 之后停止)。不抛出异常;如果没有对象可以解析,则索引不变!
这并没有告诉我为什么该方法会以这种方式运行。我从中得到的是,他们只能解析String
的一部分(他们显然在这里所做的)并且可能只是从开头(开始位置)开始解析,直到他们找到他们无法处理的东西。
我没有找到涵盖此问题的现有问题,因此如果已有问题,请随时关闭此帖子并链接到它。
【问题讨论】:
“为什么”是因为他们就是这样写的¯(°_o)/¯ 如果行为不符合您的需要,您需要将其包装或使用不同的解析机制。 【参考方案1】:NumberFormat.parse(String)
的行为与 as documented 完全相同:
从给定字符串的开头解析文本以生成一个数字。 该方法可能不会使用给定字符串的整个文本。
(已添加重点)
你问:
除了编写我自己的包装类来对例如多个小数分隔符?
您不能提供一种格式,该格式会使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();
另外,你写:
这并没有告诉我为什么该方法会以这种方式运行。
之所以这样做,是因为有时解析输入的初始部分正是您想要做的。如图所示,您可以在更轻松的解析之上构建更严格的解析,但反过来做起来就困难得多。
【讨论】:
以上是关于NumberFormat 不会因 2 个小数分隔符而崩溃的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Android 的 NumberFormat 使用逗号作为澳大利亚的小数分隔符?