小墨の博客

梦想需要付诸行动,否则只能是梦

Java字符串转数字的坑

先说最终解决方案: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进制的数字字符串,而parseLongvalueOf只能解析纯数字的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

尊重他人劳动成果,共创和谐网络环境。点击版权声明查看本站相关条款。

    发表评论:

    搜索
    本文二维码
    标签列表
    站点信息
    • 文章总数:507
    • 页面总数:20
    • 分类总数:92
    • 标签总数:207
    • 评论总数:60
    • 浏览总数:219202

    | | |
    | |  Z-Blog PHP