Java类型转换valueOf与parseInt区别探讨解析

 更新时间:2022年09月27日 11:26:55   作者:𝓼𝓲𝓭𝓲𝓸𝓽  
这篇文章主要为大家介绍了Java类型转换valueOf与parseInt区别探讨解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前言

在编程中,遇到类型转换,好像会经常用到 parseIntvalueOf,当然这里只拿 Integer 类型进行陈述,其他类型也是雷同的;

想必有读者也跟我一样,经常交叉使用这两个方法,但却不知道这两者到底有什么区别,接下来就来探究一番;  

区别

  • Integer.parseInt(s) 的作用就是把字符串 s 解析成有符号基本类型的 int;
  • Integer.valueOf(s) 把字符串 s 解析成 Integer 对象类型,返回的对象可以调用 Integer 中的方法;

接下来,通过源码进行逐一解析;  

parseInt

我们首先点进 parseInt() 方法中,

public static int parseInt(String s) throws NumberFormatException {
    return parseInt(s, 10);
}

可以看到,这个被我们调用的 parseInt() 方法返回了一个重载方法:

public static int parseInt(String s, int radix) throws NumberFormatException {
    if (s == null) {
        throw new NumberFormatException("null");
    } else if (radix < 2) {
        throw new NumberFormatException("radix " + radix + " less than Character.MIN_RADIX");
    } else if (radix > 36) {
        throw new NumberFormatException("radix " + radix + " greater than Character.MAX_RADIX");
    } else {
        boolean negative = false;
        int i = 0;
        int len = s.length();
        int limit = -2147483647;
        if (len <= 0) {
            throw NumberFormatException.forInputString(s);
        } else {
            char firstChar = s.charAt(0);
            if (firstChar < '0') {
                if (firstChar == '-') {
                    negative = true;
                    limit = -2147483648;
                } else if (firstChar != '+') {
                    throw NumberFormatException.forInputString(s);
                }
                if (len == 1) {
                    throw NumberFormatException.forInputString(s);
                }
                ++i;
            }
            int multmin = limit / radix;
            int result;
            int digit;
            for(result = 0; i < len; result -= digit) {
                digit = Character.digit(s.charAt(i++), radix);
                if (digit < 0 || result < multmin) {
                    throw NumberFormatException.forInputString(s);
                }
                result *= radix;
                if (result < limit + digit) {
                    throw NumberFormatException.forInputString(s);
                }
            }
            return negative ? result : -result;
        }
    }
}

1、首先看到的是,该方法传入了两个参数,parseInt(String s, int radix),这个可以根据被调用时传入的参数,return parseInt(s, 10);,盲猜一下,s 就是表示要转换成数字型的字符串,而 radix 英文是基数的意思,这里应该表示进制,即这个传入的字符串是多少进制的,那到底是不是呢,我们接着往下看;

2、这里先是对字符串 s 是否为空,以及 radix 的大小进行一个判断,不符合条件则抛出 NumberFormatException 异常,也就是数字格式化异常;

if (s == null){
    throw new NumberFormatException("null");
} else if (radix < 2) {
    throw new NumberFormatException("radix " + radix + " less than Character.MIN_RADIX");
} else if (radix > 36) {
    throw new NumberFormatException("radix " + radix + " greater than Character.MAX_RADIX");
} else {

3、接着往下,再一次对长度进行一个校验,

int len = s.length();
if (len <= 0) {
    throw NumberFormatException.forInputString(s);
} else {
	...
}

我在这里只想到了一个能让它抛出异常的条件,

Integer.parseInt("");

运行结果:

Exception in thread "main" java.lang.NumberFormatException: For input string: ""
    at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.base/java.lang.Integer.parseInt(Integer.java:662)
    at java.base/java.lang.Integer.parseInt(Integer.java:770)

4、接下来会检测第一个字符是啥,如果是 -,则将 negative 设置成 true,表示这是个负数,并且将边界 limit 设置成最小边界;

如果不是 +,则表示该字符既不是数字,不也是性质符号,因此抛出 NumberFormatException 异常;

如果字符串 s 的长度只有1,则表明这是非数字,不符合要求,也抛出 NumberFormatException 异常;

++i 是因为如果第一位是符号的话,那么在后续的循环中追加数字则直接跳过首位;

 char firstChar = s.charAt(0);
 if (firstChar < '0') {
     if (firstChar == '-') {
         negative = true;
         limit = -2147483648;
     } else if (firstChar != '+') {
         throw NumberFormatException.forInputString(s);
     }
     if (len == 1) {
         throw NumberFormatException.forInputString(s);
     }
     ++i;
 }

5、根据进制来调整边界,以防越界;

int multmin = limit / radix;

6、Character.digit() 用于将字符转为为对应进制的整数,如果该字符不是进制内的就返回-1,例如输入的字符是9,但是进制是2,那么就不符合,则会返回-1;

然后就是进行计算;

int result;
int digit;
for(result = 0; i < len; result -= digit) {
    digit = Character.digit(s.charAt(i++), radix);
    if (digit < 0 || result < multmin) {
        throw NumberFormatException.forInputString(s);
    }
    result *= radix;
    if (result < limit + digit) {
        throw NumberFormatException.forInputString(s);
    }
}

7、最后判断是否为负数完成转换;

return negative ? result : -result;

valueOf

照例查看源码:

public static Integer valueOf(String s, int radix) throws NumberFormatException {
    return parseInt(s, radix);
}
public static Integer valueOf(String s) throws NumberFormatException {
    return parseInt(s, 10);
}
@HotSpotIntrinsicCandidate
public static Integer valueOf(int i) {
    return i >= -128 && i <= Integer.IntegerCache.high ? Integer.IntegerCache.cache[i + 128] : new Integer(i);
}

可以看出 valueOf(String s, int radix)valueOf(String s) 都是直接调用返回了 parseInt 方法,而 valueOf(int i) 则是一个 int 转成 Integer 的自动装箱;

接下来探究一下 IntegerCache ,可以看出这是 Integer 的成员内部类,来看源码:

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer[] cache;
    static Integer[] archivedCache;
    private IntegerCache() {
    }
    static {
        int h = 127;
        String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        int size;
        if (integerCacheHighPropValue != null) {
            try {
                size = Integer.parseInt(integerCacheHighPropValue);
                size = Math.max(size, 127);
                h = Math.min(size, 2147483518);
            } catch (NumberFormatException var6) {
            }
        }
        high = h;
        VM.initializeFromArchive(Integer.IntegerCache.class);
        size = high - -128 + 1;
        if (archivedCache == null || size > archivedCache.length) {
            Integer[] c = new Integer[size];
            int j = -128;
            for(int k = 0; k < c.length; ++k) {
                c[k] = new Integer(j++);
            }
            archivedCache = c;
        }
        cache = archivedCache;
        assert high >= 127;
    }
}

整体就是初始化一个 IntegerCache.cache 数组,数组里面存储-128到127之间的数字当做是缓存,源码一开始是分析数组长度,然后给数组赋值;

总的来说,三个重构的 valueOf() 方法还是大同小异的:

  • Integer valueOf(int i):返回一个表示指定的 int 值的 Integer 实例;
  • Integer valueOf(String s):返回保存指定的 String 的值的 Integer 对象;
  • Integer valueOf(String s, int radix):返回一个 Integer 对象,该对象中保存了用第二个参数提供的基数进行解析时从指定的 String 中提取的值;

以上就是Java 中 valueOf 和 parseInt 的区别探讨解析的详细内容,更多关于Java valueOf与parseInt区别的资料请关注脚本之家其它相关文章!

相关文章

  • Java LockSupport常用方法的源码分析

    Java LockSupport常用方法的源码分析

    这篇文章主要为大家详细介绍了Java LockSupport类中的方法和部分源码,以及面试常问到的一个小问题,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-02-02
  • SpringData Redis的具体使用

    SpringData Redis的具体使用

    本文主要介绍了SpringData Redis的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-04-04
  • 深入剖析java中String、StringBuffer、StringBuilder的区别

    深入剖析java中String、StringBuffer、StringBuilder的区别

    下面小编就为大家带来一篇深入剖析java中String、StringBuffer、StringBuilder的区别。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-05-05
  • Spring Security基于JWT实现SSO单点登录详解

    Spring Security基于JWT实现SSO单点登录详解

    这篇文章主要介绍了Spring Security基于JWT实现SSO单点登录详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • Hutool开发MapUtil工具类使用示例

    Hutool开发MapUtil工具类使用示例

    这篇文章主要为大家介绍了Hutool开发MapUtil工具类使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • Java编程 多态

    Java编程 多态

    这篇文章主要介绍了关于Java编程的多态,多态通过分离做什么和怎么做,从另一个角度将接口和实现分离开来。构建可扩展的程序,需要的朋友可以参考下
    2021-10-10
  • 如何使用Code128字体将文本转换为code128条形码

    如何使用Code128字体将文本转换为code128条形码

    这篇文章主要介绍了如何使用Code128字体将文本转换为code128条形码 ,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-04-04
  • IntelliJ IDEA使用教程从入门到上瘾(2019图文版)

    IntelliJ IDEA使用教程从入门到上瘾(2019图文版)

    这篇文章主要介绍了IntelliJ IDEA使用教程从入门到上瘾(2019图文版),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • 深入理解SpringBoot的配置环境属性

    深入理解SpringBoot的配置环境属性

    SpringBoot的配置环境属性是一种强大的工具,可以帮助我们配置和管理我们的应用程序,这篇文章主要介绍了SpringBoot的配置环境属性,需要的朋友可以参考下
    2023-07-07
  • 详解基于redis实现分布式锁

    详解基于redis实现分布式锁

    系统的不断扩大,分布式锁是最基本的保障。与单机的多线程不一样的是,分布式跨多个机器。线程的共享变量无法跨机器。本文将介绍基于redis实现分布式锁。
    2021-06-06

最新评论