当前位置: 首页 > news >正文

探讨 Java 中 valueOf 和 parseInt 的区别

前言

在编程中,遇到类型转换,好像会经常用到 parseInt 和 valueOf,当然这里只拿 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 中提取的值;

http://www.lryc.cn/news/4974.html

相关文章:

  • JSON学习笔记
  • 家政服务小程序实战教程07-轮播图组件
  • MySQL之索引创建、删除、唯一索引、普通索引、及命名规则、注意事项
  • 【C++设计模式】学习笔记(3):策略模式 Strategy
  • Java——聊聊JUC中的ThreadLocal
  • 软件工程(4)--螺旋模型
  • 图解LeetCode——剑指 Offer 50. 第一个只出现一次的字符
  • 《HTML 5与CSS 3核心技法》读书笔记
  • 【沐风老师】3DMAX几何投影插件Geometry Projection使用详解
  • 面试问题整理
  • “区块链60人”2022赋能中国区块链创新人物名单公布
  • day2324 数组
  • 【Python实战】神仙运气—快看看你的彩票:2千多万元大奖无人领,马上就过期了,下一期的中奖者会是你吗?(纯技术交流)
  • 2023年上半年软考高项信息系统项目管理师2月25日开班
  • 数据库(第一天)
  • 一文了解 ArrayList 的扩容机制
  • 牛态已成选股源码
  • Python基础
  • 浅显易懂的说清楚小游戏与H5游戏的技术区别
  • 【Python入门第七天】Python 数字
  • Python自动化测试 软件测试最全教程(附笔记),看完可就业
  • Windows 安装Tomcat
  • 知识图谱业务落地技术推荐之图数据库汇总
  • 2023新华为OD机试题 - 最小传递延迟(JavaScript) | 刷完必过
  • SpringMVC基础入门(一)之理论基础概念
  • 前端知识点
  • 【docker知识】从容器中如何访问到宿主机
  • MySQL入门篇-MySQL常用流程控制函数小结
  • 大数据技术架构(组件)35——Spark:Spark Streaming(1)
  • 实现超大文件上传逻辑