先说最终解决方案:try + parseLong() 即可,下面记录一下这个坑的踩坑经历:
踩坑经历
前一阵子在写后端业务逻辑的时候遇到了String转Long的需求,一开始用的Long.parseLong,这样在转空字符串、带小数数字字符串或者其他非数字字符串的时候就会报一个异常:java.lang.NumberFormatException: For input string: "5L"
于是便修改成了Long.getLong方法,简单测试了一下,发现Long.getLong方法空字符串,非数字字符串都返回的null,不会报错,这不完美了了吗?那Entity转Dto的时候那些字段就省掉好多try catch语句了。
但是我偏偏忘了测试最重要的,正确的数字字符串也不能转换了,返回的也是null,测试如下:
System.out.println(Long.getLong("7")); // null System.out.println(Long.getLong("2")); // null System.out.println(Long.getLong("3L")); // null System.out.println(Long.getLong("-1L")); // null System.out.println(Long.getLong("1L")); // null System.out.println(Long.getLong("java.lang.Long")); // null
所以说,有时候真的不能太想当然(捂脸)
见招拆招,那干脆以Long为例,把那些字符串转数字的所有方法整理一下,省的下次遇到又走一遍老路。
new Long("7"): 构造函数传值,内部调用了parseLong()方法
Long.parseLong: 返回的是 long 基本类型(注意大小写),非数字字符串/带小数数字字符串会报NumberFormatException。
Long.valueOf: 返回的是 Long 对象,内部调用了parseLong()方法,仅仅是包装成了 Long 对象。
Long.decode: 返回的是 Long 对象,可以解析以0x、0X、#、0开头的字符串,分别表示这个字符串是16或8进制的数字字符串,而parseLong、valueOf只能解析纯数字的10进制字符串。内部调用了valueOf()方法。
Long.parseUnsignedLong: 返回的是 long 基本类型(注意大小写),字面意思,只是转无符号数字,带符号会报错java.lang.NumberFormatException: Illegal leading minus sign on unsigned string -1.,内部调用了parseLong()方法。
你看其实这些函数内部都是调用的 parseLong()/parseUnsignedLong(),其他的只是包装了一层而已,所以说,咱们还是老老实实的用 parseLong 方法+try catch捕获异常吧。
顺便说一句,其他的几个类型也是类似,大家就记住字符串转数字用 parseXxx 就行:
// 整数类型 Byte.parseByte("1"); Short.parseShort("1"); Integer.parseInt("1"); Long.parseLong("1"); // 小数类型 Float.parseFloat("1.0"); Double.parseDouble("1.0");
解决方法 & 封装工具类
可能我这个工具类写的也比较粗略,肯定有比我这样写更优雅的方式,比如可以直接引入第三方依赖比如hutool(https://www.hutool.cn/)这一类。人家有封装好的常用函数,不需要自己完成,这样封装确实能满足我的业务需求。但是,我觉得自己封装一个Util工具类其实就够了,为了这一个小问题引入一个依赖,我觉得没太大必要,大家可以根据自己项目实际情况自行决定。
public class NumberParseUtils { /** * Long 转 String 工具类 * <p> * 非数字类型字符串getLong之后为null,不会报错 * * @param str * @return 转换失败时不报错,返回 null */ public static Long parseLong(String str) { return parseLong(str, null); } /** * Long 转 String 工具类 * <p> * 非数字类型字符串getLong之后为null,不会报错 * * @param str * @return 转换失败时不报错,返回 defaultValue */ public static Long parseLong(String str, Long defaultValue) { if (str == null) { return defaultValue; } try { return Long.parseLong(str); } catch (NumberFormatException e) { return defaultValue; } } }
测试用例
测试用例如下:
import com.example.backend.common.Utils.NumberParseUtils; public class NumberParseUtilsTest { public static void main(String[] args) { System.out.println("new Long"); System.out.println(new Long("7")); System.out.println("Long.getLong"); System.out.println(Long.getLong("7")); // null System.out.println(Long.getLong("2")); // null System.out.println(Long.getLong("3L")); // null System.out.println(Long.getLong("-1L")); // null System.out.println(Long.getLong("1L")); // null System.out.println(Long.getLong("java.lang.Long")); // null // long System.out.println("Long.parseLong"); System.out.println(Long.parseLong("-1")); // -1 System.out.println(Long.parseLong("3")); // 3 // System.out.println(Long.parseLong("5L")); // Exception in thread "main" java.lang.NumberFormatException: For input string: "5L" // Long System.out.println("Long.valueOf"); System.out.println(Long.valueOf("-1")); // -1 System.out.println(Long.valueOf("3")); // 3 // System.out.println(Long.valueOf("5L")); // Exception in thread "main" java.lang.NumberFormatException: For input string: "5L" System.out.println(Long.valueOf("011")); // 输出11 // System.out.println(Long.valueOf("#11")); // 出错 // System.out.println(Long.valueOf("0X11"));// 出错 // System.out.println(Long.valueOf("0x11"));// 出错 System.out.println(Long.valueOf("11")); // 输出11 System.out.println("Long.decode"); System.out.println(Long.decode("-1")); // -1 System.out.println(Long.decode("3")); // 3 // System.out.println(Long.decode("5L")); // Exception in thread "main" java.lang.NumberFormatException: For input string: "5L" System.out.println(Long.decode("011")); // 8进制,输出9 System.out.println(Long.decode("#11")); // 16进制,输出17 System.out.println(Long.decode("0X11"));// 16进制,输出17 System.out.println(Long.decode("0x11"));// 16进制,输出17 System.out.println(Long.decode("11")); // 10进制,输出11 System.out.println("Long.parseUnsignedLong"); // System.out.println(Long.parseUnsignedLong("-1")); // Exception in thread "main" java.lang.NumberFormatException: Illegal leading minus sign on unsigned string -1. System.out.println(Long.parseUnsignedLong("3")); // 3 // System.out.println(Long.parseUnsignedLong("5L")); // Exception in thread "main" java.lang.NumberFormatException: For input string: "5L" System.out.println("NumberParseUtils.parseLong"); System.out.println(NumberParseUtils.parseLong("1")); System.out.println(NumberParseUtils.parseLong("")); System.out.println(NumberParseUtils.parseLong("0")); System.out.println(NumberParseUtils.parseLong("3487215432148412423")); // 19位,可以正常解析 System.out.println(NumberParseUtils.parseLong("34872154321484124234")); // 20位,返回null // 为小数值时,String类型不能转为Long类型 System.out.println(NumberParseUtils.parseLong("0.5")); System.out.println(NumberParseUtils.parseLong("-3.2L")); System.out.println(NumberParseUtils.parseLong("abc")); System.out.println(NumberParseUtils.parseLong(null)); } }
张小弟之家原创,转载请标注原作者及本页链接
本站文章除注明转载/出处外,均为原创,若要转载请务必注明出处。转载后请将转载链接通过邮件告知我站,谢谢合作。本站邮箱:admin@only4.work
尊重他人劳动成果,共创和谐网络环境。点击版权声明查看本站相关条款。