From 1dbfb361465bf0d4edd7996b44542948db26bacb Mon Sep 17 00:00:00 2001 From: ZhouXY108 Date: Wed, 3 Sep 2025 21:37:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20`Numbers`=20=E7=B1=BB=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=20`parseXxx`=20=E6=96=B9=E6=B3=95=20(#65=20@Gitea)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `Numbers` 类新增 `parseXxx` 方法用于将字符串转为对应类型的数字,当转换失败时返回默认值。默认值允许为 `null`。 --- .../zhouxy/plusone/commons/util/Numbers.java | 123 +++++++++++++++++- .../plusone/commons/util/NumbersTests.java | 95 ++++++++++++++ 2 files changed, 217 insertions(+), 1 deletion(-) diff --git a/plusone-commons/src/main/java/xyz/zhouxy/plusone/commons/util/Numbers.java b/plusone-commons/src/main/java/xyz/zhouxy/plusone/commons/util/Numbers.java index 29e7e02..18322eb 100644 --- a/plusone-commons/src/main/java/xyz/zhouxy/plusone/commons/util/Numbers.java +++ b/plusone-commons/src/main/java/xyz/zhouxy/plusone/commons/util/Numbers.java @@ -29,7 +29,9 @@ import javax.annotation.Nullable; */ public class Numbers { + // ================================ // #region - sum + // ================================ /** * 求和 @@ -131,9 +133,13 @@ public class Numbers { return BigDecimals.sum(numbers); } + // ================================ // #endregion + // ================================ + // ================================ // #region - nullToZero + // ================================ /** * 将 {@code null} 转换为 {@code 0} @@ -217,7 +223,122 @@ public class Numbers { return BigDecimals.nullToZero(val); } - // #endregion + // ================================ + // #endregion - nullToZero + // ================================ + + // ================================ + // #region - parse + // ================================ + + /** + * 将字符串转为对应 {@link Short},转换失败时返回 {@code defaultValue}(允许为 {@code null})。 + * + * @param str 要转换的字符串 + * @param defaultValue 默认值 + * @return 转换结果 + */ + @Nullable + public static Short parseShort(@Nullable String str, @Nullable Short defaultValue) { + if (StringTools.isBlank(str)) { + return defaultValue; + } + try { + return Short.parseShort(str); + } + catch (NumberFormatException ignore) { + // ignore + } + return defaultValue; + } + + /** + * 将字符串转为 {@link Integer},转换失败时返回 {@code defaultValue}(允许为 {@code null})。 + * + * @param str 要转换的字符串 + * @param defaultValue 默认值 + * @return 转换结果 + */ + @Nullable + public static Integer parseInteger(@Nullable String str, @Nullable Integer defaultValue) { + if (StringTools.isBlank(str)) { + return defaultValue; + } + try { + return Integer.parseInt(str); + } + catch (NumberFormatException ignore) { + // ignore + } + return defaultValue; + } + + /** + * 将字符串转为 {@link Long},转换失败时返回 {@code defaultValue}(允许为 {@code null})。 + * + * @param str 要转换的字符串 + * @param defaultValue 默认值 + * @return 转换结果 + */ + @Nullable + public static Long parseLong(@Nullable String str, @Nullable Long defaultValue) { + if (StringTools.isBlank(str)) { + return defaultValue; + } + try { + return Long.parseLong(str); + } + catch (NumberFormatException ignore) { + // ignore + } + return defaultValue; + } + + /** + * 将字符串转为 {@link Float},转换失败时返回 {@code defaultValue}(允许为 {@code null})。 + * + * @param str 要转换的字符串 + * @param defaultValue 默认值 + * @return 转换结果 + */ + @Nullable + public static Float parseFloat(@Nullable String str, @Nullable Float defaultValue) { + if (StringTools.isBlank(str)) { + return defaultValue; + } + try { + return Float.parseFloat(str); + } + catch (NumberFormatException ignore) { + // ignore + } + return defaultValue; + } + + /** + * 将字符串转为 {@link Double},转换失败时返回 {@code defaultValue}(允许为 {@code null})。 + * + * @param str 要转换的字符串 + * @param defaultValue 默认值 + * @return 转换结果 + */ + @Nullable + public static Double parseDouble(@Nullable String str, @Nullable Double defaultValue) { + if (StringTools.isBlank(str)) { + return defaultValue; + } + try { + return Double.parseDouble(str); + } + catch (NumberFormatException ignore) { + // ignore + } + return defaultValue; + } + + // ================================ + // #endregion - parse + // ================================ private Numbers() { throw new IllegalStateException("Utility class"); diff --git a/plusone-commons/src/test/java/xyz/zhouxy/plusone/commons/util/NumbersTests.java b/plusone-commons/src/test/java/xyz/zhouxy/plusone/commons/util/NumbersTests.java index 0f8b9b1..453daab 100644 --- a/plusone-commons/src/test/java/xyz/zhouxy/plusone/commons/util/NumbersTests.java +++ b/plusone-commons/src/test/java/xyz/zhouxy/plusone/commons/util/NumbersTests.java @@ -26,6 +26,7 @@ import java.util.Arrays; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; public @@ -192,6 +193,100 @@ class NumbersTests { assertEquals(BigDecimal.ZERO, result); } + /** + * Test for {@link Numbers#parseShort(String, Short)}. + */ + @Test + public void parseShort() { + assertEquals((short) 12345, Numbers.parseShort("12345", (short) 5)); + assertEquals((short) 5, Numbers.parseShort("1234.5", (short) 5)); + assertEquals((short) 5, Numbers.parseShort("", (short) 5)); + assertEquals((short) 5, Numbers.parseShort(null, (short) 5)); + + assertEquals((short) 12345, Numbers.parseShort("12345", null)); + assertNull(Numbers.parseShort("1234.5", null)); + assertNull(Numbers.parseShort("", null)); + assertNull(Numbers.parseShort(null, null)); + } + + /** + * Test for {@link Numbers#parseInteger(String, Integer)}. + */ + @Test + public void parseInteger() { + assertEquals(12345, Numbers.parseInteger("12345", 5)); + assertEquals(5, Numbers.parseInteger("1234.5", 5)); + assertEquals(5, Numbers.parseInteger("", 5)); + assertEquals(5, Numbers.parseInteger(null, 5)); + + assertEquals(12345, Numbers.parseInteger("12345", null)); + assertNull(Numbers.parseInteger("1234.5", null)); + assertNull(Numbers.parseInteger("", null)); + assertNull(Numbers.parseInteger(null, null)); + } + + /** + * Test for {@link Numbers#parseLong(String, Long)}. + */ + @Test + public void parseLong() { + assertEquals(12345L, Numbers.parseLong("12345", 5L)); + assertEquals(5L, Numbers.parseLong("1234.5", 5L)); + assertEquals(5L, Numbers.parseLong("", 5L)); + assertEquals(5L, Numbers.parseLong(null, 5L)); + + assertEquals(12345L, Numbers.parseLong("12345", null)); + assertNull(Numbers.parseLong("1234.5", null)); + assertNull(Numbers.parseLong("", null)); + assertNull(Numbers.parseLong(null, null)); + } + + /** + * Test for {@link Numbers#parseFloat(String, Float)}. + */ + @Test + public void parseFloat() { + assertEquals(1.2345f, Numbers.parseFloat("1.2345", 5.1f)); + assertEquals(5.0f, Numbers.parseFloat("a", 5.0f)); + assertEquals(5.0f, Numbers.parseFloat("-001Z.2345", 5.0f)); + assertEquals(5.0f, Numbers.parseFloat("+001AB.2345", 5.0f)); + assertEquals(5.0f, Numbers.parseFloat("001Z.2345", 5.0f)); + assertEquals(5.0f, Numbers.parseFloat("", 5.0f)); + assertEquals(5.0f, Numbers.parseFloat(null, 5.0f)); + + assertEquals(1.2345f, Numbers.parseFloat("1.2345", null)); + assertNull(Numbers.parseFloat("a", null)); + assertNull(Numbers.parseFloat("-001Z.2345", null)); + assertNull(Numbers.parseFloat("+001AB.2345", null)); + assertNull(Numbers.parseFloat("001Z.2345", null)); + assertNull(Numbers.parseFloat("", null)); + assertNull(Numbers.parseFloat(null, null)); + } + + /** + * Test for {@link Numbers#parseDouble(String, Double)}. + */ + @Test + public void parseDouble() { + assertEquals(1.2345d, Numbers.parseDouble("1.2345", 5.1d)); + assertEquals(5.0d, Numbers.parseDouble("a", 5.0d)); + assertEquals(1.2345d, Numbers.parseDouble("001.2345", 5.1d)); + assertEquals(-1.2345d, Numbers.parseDouble("-001.2345", 5.1d)); + assertEquals(1.2345d, Numbers.parseDouble("+001.2345", 5.1d)); + assertEquals(0d, Numbers.parseDouble("000.00", 5.1d)); + assertEquals(5.1d, Numbers.parseDouble("", 5.1d)); + assertEquals(5.1d, Numbers.parseDouble((String) null, 5.1d)); + + assertEquals(1.2345d, Numbers.parseDouble("1.2345", null)); + assertEquals(null, Numbers.parseDouble("a", null)); + assertEquals(1.2345d, Numbers.parseDouble("001.2345", null)); + assertEquals(-1.2345d, Numbers.parseDouble("-001.2345", null)); + assertEquals(1.2345d, Numbers.parseDouble("+001.2345", null)); + assertEquals(0d, Numbers.parseDouble("000.00", null)); + assertEquals(null, Numbers.parseDouble("", null)); + assertEquals(null, Numbers.parseDouble((String) null, null)); + } + @Test void test_constructor_isNotAccessible_ThrowsIllegalStateException() { Constructor[] constructors = Numbers.class.getDeclaredConstructors();