From 9a1ed650a81b6753948b151d0280e33046f8c4e4 Mon Sep 17 00:00:00 2001 From: Zjp <1215582715@qq.com> Date: Thu, 17 Nov 2022 17:24:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=90=AC=E8=BF=90apache-NumberUtils.isCreatabl?= =?UTF-8?q?e=E6=96=B9=E6=B3=95=E5=8F=8A=E6=B5=8B=E8=AF=95=E7=94=A8?= =?UTF-8?q?=E4=BE=8B;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/core/math/NumberUtil.java | 21 ++++-- .../cn/hutool/core/util/NumberUtilTest.java | 72 +++++++++++++++++-- 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/math/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/math/NumberUtil.java index 90cdf7c84..9a7a65341 100644 --- a/hutool-core/src/main/java/cn/hutool/core/math/NumberUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/math/NumberUtil.java @@ -639,9 +639,10 @@ public class NumberUtil { * 3、科学计数法形式(1234E3) * 4、类型标识形式(123D) * 5、正负数标识形式(+123、-234) + * 6、八进制数字(0开头) * * - * @param str 字符串值 + * @param str 字符串值, 不可以含有任何空白字符 * @return 是否为数字 */ public static boolean isNumber(final CharSequence str) { @@ -656,8 +657,8 @@ public class NumberUtil { boolean foundDigit = false; // deal with any possible sign up front final int start = (chars[0] == '-' || chars[0] == '+') ? 1 : 0; - if (sz > start + 1) { - if (chars[start] == '0' && (chars[start + 1] == 'x' || chars[start + 1] == 'X')) { + if (sz > start + 1 && chars[start] == '0' && !StrUtil.contains(str, CharUtil.DOT)) { // leading 0, skip if is a decimal number + if (chars[start + 1] == 'x' || chars[start + 1] == 'X') { // leading 0x/0X int i = start + 2; if (i == sz) { return false; // str == "0x" @@ -670,6 +671,16 @@ public class NumberUtil { } return true; } + if (Character.isDigit(chars[start + 1])) { + // leading 0, but not hex, must be octal + int i = start + 1; + for (; i < chars.length; i++) { + if (chars[i] < '0' || chars[i] > '7') { + return false; + } + } + return true; + } } sz--; // don't want to loop to the last char, check it afterwords // for type qualifiers @@ -730,8 +741,8 @@ public class NumberUtil { return foundDigit; } if (chars[i] == 'l' || chars[i] == 'L') { - // not allowing L with an exponent - return foundDigit && !hasExp; + // not allowing L with an exponent or decimal point + return foundDigit && !hasExp && !hasDecPoint; } // last character is illegal return false; diff --git a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java index 69e67d368..2d0b8f367 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java @@ -104,11 +104,73 @@ public class NumberUtilTest { @Test public void isNumberTest() { - Assert.assertTrue(NumberUtil.isNumber("28.55")); - Assert.assertTrue(NumberUtil.isNumber("0")); - Assert.assertTrue(NumberUtil.isNumber("+100.10")); - Assert.assertTrue(NumberUtil.isNumber("-22.022")); - Assert.assertTrue(NumberUtil.isNumber("0X22")); + privateIsNumberTest("28.55", true); + privateIsNumberTest("12345", true); + privateIsNumberTest("1234.5", true); + privateIsNumberTest(".12345", true); + privateIsNumberTest("1234E5", true); + privateIsNumberTest("1234E+5", true); + privateIsNumberTest("1234E-5", true); + privateIsNumberTest("123.4E5", true); + privateIsNumberTest("-1234", true); + privateIsNumberTest("-1234.5", true); + privateIsNumberTest("-.12345", true); + privateIsNumberTest("-1234E5", true); + privateIsNumberTest("0", true); + privateIsNumberTest("0.1", true); // LANG-1216 + privateIsNumberTest("-0", true); + privateIsNumberTest("01234", true); + privateIsNumberTest("-01234", true); + privateIsNumberTest("-0xABC123", true); + privateIsNumberTest("-0x0", true); + privateIsNumberTest("123.4E21D", true); + privateIsNumberTest("-221.23F", true); + privateIsNumberTest("22338L", true); + + privateIsNumberTest(null, false); + privateIsNumberTest("", false); + privateIsNumberTest(" ", false); + privateIsNumberTest("\r\n\t", false); + privateIsNumberTest("--2.3", false); + privateIsNumberTest(".12.3", false); + privateIsNumberTest("-123E", false); + privateIsNumberTest("-123E+-212", false); + privateIsNumberTest("-123E2.12", false); + privateIsNumberTest("0xGF", false); + privateIsNumberTest("0xFAE-1", false); + privateIsNumberTest(".", false); + privateIsNumberTest("-0ABC123", false); + privateIsNumberTest("123.4E-D", false); + privateIsNumberTest("123.4ED", false); + privateIsNumberTest("1234E5l", false); + privateIsNumberTest("11a", false); + privateIsNumberTest("1a", false); + privateIsNumberTest("a", false); + privateIsNumberTest("11g", false); + privateIsNumberTest("11z", false); + privateIsNumberTest("11def", false); + privateIsNumberTest("11d11", false); + privateIsNumberTest("11 11", false); + privateIsNumberTest(" 1111", false); + privateIsNumberTest("1111 ", false); + + privateIsNumberTest("2.", true); // LANG-521 + privateIsNumberTest("1.1L", false); // LANG-664 + privateIsNumberTest("+0xF", true); // LANG-1645 + privateIsNumberTest("+0xFFFFFFFF", true); // LANG-1645 + privateIsNumberTest("+0xFFFFFFFFFFFFFFFF", true); // LANG-1645 + privateIsNumberTest(".0", true); // LANG-1646 + privateIsNumberTest("0.", true); // LANG-1646 + privateIsNumberTest("0.D", true); // LANG-1646 + privateIsNumberTest("0e1", true); // LANG-1646 + privateIsNumberTest("0e1D", true); // LANG-1646 + privateIsNumberTest(".D", false); // LANG-1646 + privateIsNumberTest(".e10", false); // LANG-1646 + privateIsNumberTest(".e10D", false); // LANG-1646 + } + + private void privateIsNumberTest(final String numStr, final boolean expected) { + Assert.assertEquals(expected, NumberUtil.isNumber(numStr)); } @Test