Java类型转换valueOf parseInt
人气:0前言
在编程中,遇到类型转换,好像会经常用到 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 中提取的值;
加载全部内容