String轉(zhuǎn)換成Integer源碼區(qū)分
發(fā)表時(shí)間:2024-02-16 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]我們經(jīng)常為用到Integer.valueOf(String str)這個(gè)方法,如果字符串格式不對(duì),這個(gè)方法會(huì)拋出一個(gè)系統(tǒng)異常NumberFormatException這里我們就要分析一下這個(gè)方法,其中Byte,Short也是調(diào)用了Ingeter中的方法.在Integer類中的定義如下:public...
我們經(jīng)常為用到Integer.valueOf(String str)這個(gè)方法,如果字符串格式不對(duì),這個(gè)方法會(huì)拋出一個(gè)系統(tǒng)異常NumberFormatException
這里我們就要分析一下這個(gè)方法,其中Byte,Short也是調(diào)用了Ingeter中的方法.
在Integer類中的定義如下:
public static Integer valueOf(String s) throws NumberFormatException
{
return new Integer(parseInt(s, 10));
}
這里因?yàn)閜arseInt方法返回的int型的,這里調(diào)用了一個(gè)構(gòu)造函數(shù)產(chǎn)生了一個(gè)新的Integer實(shí)例.
這里關(guān)心的是parseInt方法,該方法代碼如下:
public static int parseInt(String s, int radix)
throws NumberFormatException
{
if (s == null) {
throw new NumberFormatException("null");
}
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}
int result = 0;
boolean negative = false;
int i = 0, max = s.length();
int limit;
int multmin;
int digit;
if (max > 0) {
if (s.charAt(0) == '-') {
negative = true;
limit = Integer.MIN_VALUE;
i++;
} else {
limit = -Integer.MAX_VALUE;
}
if (i < max) {
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
} else {
result = -digit;
}
}
while (i < max) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
if (result < multmin) {
throw NumberFormatException.forInputString(s); 異常1
}
result *= radix;
if (result < limit + digit) {
throw NumberFormatException.forInputString(s); 異常2
}
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
if (negative) {
if (i > 1) {
return result;
} else { /* Only got "-" */
throw NumberFormatException.forInputString(s);
}
} else {
return -result;
}
}
很顯然,該方法的第二個(gè)參數(shù)表示是基數(shù)(最常用的是十進(jìn)制,還有十六機(jī)制,八進(jìn)制等等).
如果字符串是空指針,直接拋出異常.
如果基礎(chǔ)小于2或者大于36的話,拋出異常(這種情況一般不會(huì)出現(xiàn),因?yàn)槲覀冇玫淖疃嗑褪鞘M(jìn)制的了).
如果是空字符串,也拋出異常,也就是max=0的情況了.
我們來(lái)關(guān)注下面的轉(zhuǎn)換過(guò)程:
這里使用了Character中的靜態(tài)方法digit,這個(gè)方法比較復(fù)雜,這里先說(shuō)明它的功能:對(duì)于給定的基數(shù),如果是合法的字符(可以轉(zhuǎn)化為數(shù)字),返回該數(shù)字值,否則返回-1.比如digit('3',10)返回3,digit('a',10)返回-1.
這段程序看起來(lái)很簡(jiǎn)單,其實(shí)還真不容易看懂,這里先說(shuō)明幾個(gè)局部變量的含義吧:
result:記錄返回值
negative:符號(hào)標(biāo)志
i:字符串位置
s:字符串長(zhǎng)度
limit:界限
multmin:也是一個(gè)界限
digit:當(dāng)前字符表示的數(shù)字
先看第一個(gè)字符是否是'-'號(hào),設(shè)定符號(hào)標(biāo)志negative和極限值limit.
注意到limit一定是一個(gè)負(fù)值.
處理最高位,這里result保存的是負(fù)值,這樣就可以對(duì)正負(fù)數(shù)統(tǒng)一處理.
關(guān)鍵就是這個(gè)while循環(huán)了,第一個(gè)if不用解釋了,肯定是因?yàn)榉欠ㄗ址?
第二個(gè)if語(yǔ)句的含義:如果result小于multmin,會(huì)產(chǎn)生什么結(jié)果呢?
是不是一定會(huì)溢出呢?假設(shè)不會(huì)溢出,就是說(shuō)結(jié)果必須>=limit.
result小于multmin,result至少應(yīng)該位multmin-1,后面有result=result*radix=(multmin-1)*radix=multmin*radix-radix
該值肯定小于limit,其中multmin=limit/radix,注意這里都是負(fù)數(shù).
所以假設(shè)不成里,如果result小于multmin的話,后面一定會(huì)溢出.
如果這里沒(méi)有判斷的話,溢出就麻煩了,正數(shù)也會(huì)變負(fù)數(shù)了.
第三個(gè)if語(yǔ)句的含義:在這條語(yǔ)句以前肯定沒(méi)有溢出,但是有可能加上最后一位digit就溢出了,所以這個(gè)判斷也是必要的.
后面的就比較好理解了,else是表示空字符串"".
如果是負(fù)數(shù)的還要看是否長(zhǎng)度是1,就只是一個(gè)'-'號(hào)的情況.
如果是正數(shù)的話返回相反數(shù)就可以了.
這里有好多地方都有可能拋出異常,只要看明白了程序就知道這個(gè)異常是那條語(yǔ)句拋出的了,這里考慮溢出異常:異常1和異常2.
Ingeter.Max_VALUE=2147483647
下面的兩條語(yǔ)句在不同的地方拋出異常.
Ingeter.valueOf("2147483648");這個(gè)在異常2拋出的.
Ingeter.valueOf("21474836471");這個(gè)在異常1拋出的.
這里簡(jiǎn)單的分析了String轉(zhuǎn)化為Ingeter的過(guò)程,其實(shí)整個(gè)Ingeter類也就主要是這個(gè)方法了,Byte和Short都是調(diào)用這個(gè)方法的.
看看Byte的代碼:
public static byte parseByte(String s, int radix)
throws NumberFormatException {
int i = Integer.parseInt(s, radix);
if (i < MIN_VALUE i > MAX_VALUE)
throw new NumberFormatException(
"Value out of range. Value:\"" + s + "\" Radix:" + radix);
return (byte)i;
}
了解這個(gè)方法后就再也不會(huì)為Integer.valueOf()產(chǎn)生的異常感到意外了,特別是在JSP中,因?yàn)閰?shù)都是String型的,轉(zhuǎn)換的時(shí)候動(dòng)不動(dòng)就出現(xiàn)異常,你該知道怎么回事了吧.