我們經常為用到Integer.valueOf(String str)這個方法,如果字符串格式不對,這個方法會拋出一個系統異常NumberFormatException 這里我們就要分析一下這個方法,其中Byte,Short也是調用了Ingeter中的方法. 在Integer類中的定義如下: public static Integer valueOf(String s) throws NumberFormatException { return new Integer(parseInt(s, 10)); } 這里因為parseInt方法返回的int型的,這里調用了一個構造函數產生了一個新的Integer實例. 這里關心的是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; } }
很顯然,該方法的第二個參數表示是基數(最常用的是十進制,還有十六機制,八進制等等). 如果字符串是空指針,直接拋出異常. 如果基礎小于2或者大于36的話,拋出異常(這種情況一般不會出現,因為我們用的最多就是十進制的了). 如果是空字符串,也拋出異常,也就是max=0的情況了. 我們來關注下面的轉換過程: 這里使用了Character中的靜態方法digit,這個方法比較復雜,這里先說明它的功能:對于給定的基數,如果是合法的字符(可以轉化為數字),返回該數字值,否則返回-1.比如digit('3',10)返回3,digit('a',10)返回-1. 這段程序看起來很簡單,其實還真不容易看懂,這里先說明幾個局部變量的含義吧: result:記錄返回值 negative:符號標志 i:字符串位置 s:字符串長度 limit:界限 multmin:也是一個界限 digit:當前字符表示的數字 先看第一個字符是否是'-'號,設定符號標志negative和極限值limit. 注意到limit一定是一個負值. 處理最高位,這里result保存的是負值,這樣就可以對正負數統一處理. 關鍵就是這個while循環了,第一個if不用解釋了,肯定是因為非法字符. 第二個if語句的含義:如果result小于multmin,會產生什么結果呢? 是不是一定會溢出呢?假設不會溢出,就是說結果必須>=limit. result小于multmin,result至少應該位multmin-1,后面有result=result*radix=(multmin-1)*radix=multmin*radix-radix 該值肯定小于limit,其中multmin=limit/radix,注意這里都是負數. 所以假設不成里,如果result小于multmin的話,后面一定會溢出. 如果這里沒有判斷的話,溢出就麻煩了,正數也會變負數了. 第三個if語句的含義:在這條語句以前肯定沒有溢出,但是有可能加上最后一位digit就溢出了,所以這個判斷也是必要的. 后面的就比較好理解了,else是表示空字符串"". 如果是負數的還要看是否長度是1,就只是一個'-'號的情況. 如果是正數的話返回相反數就可以了. 這里有好多地方都有可能拋出異常,只要看明白了程序就知道這個異常是那條語句拋出的了,這里考慮溢出異常:異常1和異常2. Ingeter.Max_VALUE=2147483647 下面的兩條語句在不同的地方拋出異常. Ingeter.valueOf("2147483648");這個在異常2拋出的. Ingeter.valueOf("21474836471");這個在異常1拋出的.
這里簡單的分析了String轉化為Ingeter的過程,其實整個Ingeter類也就主要是這個方法了,Byte和Short都是調用這個方法的. 看看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; }
了解這個方法后就再也不會為Integer.valueOf()產生的異常感到意外了,特別是在JSP中,因為參數都是String型的,轉換的時候動不動就出現異常,你該知道怎么回事了吧.
|