大家都知道int 是基本数据类型而Integer则是int的包装类,为什么要为基本数据类型提供包装类呢?这里我只说一个最基本的原因 “为了在各种类型间转化,通过各种方法的调用。否则 你无法直接通过变量转化”,这只是其一,其余的我就不一一赘述了,下面让我们来一下Integer的源码
public static final int MIN_VALUE = 0x80000000; //Integer中所能存储的最大值,即2的31次方减一。
public static final int MAX_VALUE = 0x7fffffff; //Integer中所能存储的最小值,即负2的31次方 减一。
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int"); //原始类型int的Class实例。
final static char[] digits = {
'0' , '1' , '2' , '3' , '4' , '5' ,
'6' , '7' , '8' , '9' , 'a' , 'b' ,
'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
'o' , 'p' , 'q' , 'r' , 's' , 't' ,
'u' , 'v' , 'w' , 'x' , 'y' , 'z'
}; //所有可能的将数字表示为字符串的字符集合。
//返回第二个参数所指定的进制数的第一个参数的字符串表示形式
我们可以通过上面的代码看到Integer继承了Number,对于Number这个类这里就不讲了,并且实现了Comparable接口,并且声明了int的最大值与最小值,声明了一个digits数组,用以数据类型转换
下面就是toString方法 :
我们知道这个toString方法有两个重载方法一个方法只传入一个int值,另一个方法传入两个int值,在这里我们先讲解传入两个参数的toString方法,第一个参数是我们需要转成String的int值,第二个参数radix则是需要将这个int值转换成几进制(2 - 36),然后转换成字符串
下面是代码 :
public static String toString(int i, int radix) {
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) //判断radix是否在2到36之间,如果超过了就将radix = 10,让下面判断等于10 直接调用另一个toString方法直接转换成10进制的字符串
radix = 10;
/* Use the faster version */
if (radix == 10) {
return toString(i);
}
/*
如果传入的radix在 2到36之间的话,就直接进行下面的进制转换
*/
char buf[] = new char[33];
boolean negative = (i < 0); //要转化的值为负数时,将negative设置为true
int charPos = 32;
if (!negative) {
i = -i; //如果i为负数先将它转为整数
}
while (i <= -radix) { //进制转换
buf[charPos--] = digits[-(i % radix)];
i = i / radix;
}
buf[charPos] = digits[-i];
if (negative) {
buf[--charPos] = '-'; //如果是负数就将第一加上 '-'
}
return new String(buf, charPos, (33 - charPos)); //返回一个字符串
}
这就是 toString(int i ,radix)了,现在我们来看一下另一种只传入一个参数的toString方法,
public static String toString(int i) {
if (i == Integer.MIN_VALUE)
return "-2147483648";//如果传入的是inteager的最小值也就是 -2的31的次方 直接返回最小值
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); //如果i为负数,则字符串长度要加1。
char[] buf = new char[size];
getChars(i, size, buf); //获取i中字符的集合。
return new String(buf, true);//返回字符串
}
现在来讲解,Integer的parseInt方法,这个方法我们经常性的用来进行类型转换,并且这个方法还重载了两个,一个是传入一个字符串将其转换为int值,还有一个就是传入一个字符串和radix,相信radix这个变量我们已经很熟悉了,就toString 的radix是一样的,代表着几进制,下面让我们来了解一下这个函数
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");//检查radix是否在 2 到 36之间
}
if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}
int result = 0;
boolean negative = false;
int i = 0, len = s.length(); //i表示当前遍历的s的位数
int limit = -Integer.MAX_VALUE; //设置最小值为负的Integer的最大值
int multmin;
int digit;
if (len > 0) { //如果字符串长度大于0,则进行转换
char firstChar = s.charAt(0); //获取第一位字符
//在第一位字符小于'0'的情况下,判定是否含有符号'+'、'-'
if (firstChar < '0') { // Possible leading "+" or "-"
if (firstChar == '-') { //为负数的情况
negative = true;
limit = Integer.MIN_VALUE; //不能小于Integer的最小值
} else if (firstChar != '+') //不为'-'时,如果不为'+',则表示符号错误。
throw NumberFormatException.forInputString(s);
//如果字符串的长度等于1,且这个字符小于'0',则表示该字符串仅为一个符号,抛出异常
if (len == 1) // Cannot have lone "+" or "-"
throw NumberFormatException.forInputString(s);
i++;
}
multmin = limit / radix;
while (i < len) { //进行进制的转换
// 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);
}
result *= radix;
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
return negative ? result : -result; //根据符号返回正数还是负数
}
这就是传入两个参数的parseInt了,接下来只传入一个参数parseInt,相信大家已经知道了,非常简单的直接调用了parseInt(s,10);然后返回
public static int parseInt(String s) throws NumberFormatException {
return parseInt(s,10);
}
接下来要讲的就是Inteager.valueOf()了,这个方法相信已经很多用过了,对的,没错他的功能就是将String转换成Integer对象,关于这个方法
(1)调用Integer类中的静态方法valueOf(String)
(2)valueOf方法将传入的参数String转化为int型值
(3)返回该值,如果String并不是纯粹由数字构成即无法转化为数字,则抛出NumberFormatException
当然这个方法也有三个重载方法,valueOf(int i)直接返回一个实例 valueOf(String s, int radix) 调用parseInt 转换成int值 valueOf(String s) 调用Integer.valueOf(parseInt(s, 10)); 下面是代码 *
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127; //断言Integer缓存中的上届必须大于或等于127
if (i >= IntegerCache.low && i <= IntegerCache.high) //如果i在Integer缓存中,则直接取出
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i); //否则,直接创建一个实例
}
public static Integer valueOf(String s, int radix) throws NumberFormatException {
return Integer.valueOf(parseInt(s,radix));
}
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
好了 讲的差不多了,下面是完整的代码
import java.util.Properties;
public final class Integer extends Number implements Comparable<Integer> {
public static final int MIN_VALUE = 0x80000000; //Integer中所能存储的最大值,即231-1。
public static final int MAX_VALUE = 0x7fffffff; //Integer中所能存储的最小值,即2-31。
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int"); //原始类型int的Class实例。
final static char[] digits = {
'0' , '1' , '2' , '3' , '4' , '5' ,
'6' , '7' , '8' , '9' , 'a' , 'b' ,
'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
'o' , 'p' , 'q' , 'r' , 's' , 't' ,
'u' , 'v' , 'w' , 'x' , 'y' , 'z'
}; //所有可能的将数字表示为字符串的字符集合。
//返回第二个参数所指定的进制数的第一个参数的字符串表示形式
public static String toString(int i, int radix) {
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
radix = 10;
/* Use the faster version */
if (radix == 10) {
return toString(i);
}
char buf[] = new char[33];
boolean negative = (i < 0);
int charPos = 32;
if (!negative) {
i = -i;
}
while (i <= -radix) {
buf[charPos--] = digits[-(i % radix)];
i = i / radix;
}
buf[charPos] = digits[-i];
if (negative) {
buf[--charPos] = '-';
}
return new String(buf, charPos, (33 - charPos));
}
public static String toHexString(int i) {
return toUnsignedString(i, 4);
}
public static String toOctalString(int i) {
return toUnsignedString(i, 3);
}
public static String toBinaryString(int i) {
return toUnsignedString(i, 1);
}
//转换int类型为无符号的字符串
private static String toUnsignedString(int i, int shift) {
char[] buf = new char[32];
int charPos = 32;
int radix = 1 << shift; //使用左移操作符,提升性能。
int mask = radix - 1;
do {
buf[--charPos] = digits[i & mask]; //使用&位移操作符得出每一位上的数字。
i >>>= shift; //移除已经得到的数字
} while (i != 0);
return new String(buf, charPos, (32 - charPos));
}
//十位数上的字符集
final static char [] DigitTens = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
'3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
'4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
'5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
'7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
'8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
'9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
} ;
//个位数上的字符集
final static char [] DigitOnes = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
} ;
public static String toString(int i) {
if (i == Integer.MIN_VALUE)
return "-2147483648";
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); //如果i为负数,则字符串长度要加1。
char[] buf = new char[size];
getChars(i, size, buf); //获取i中字符的集合。
return new String(buf, true);
}
static void getChars(int i, int index, char[] buf) {
int q, r;
int charPos = index;
char sign = 0;
if (i < 0) { //如果i为负数,则设置i的符号字符为'-'。
sign = '-';
i = -i;
}
// Generate two digits per iteration
while (i >= 65536) { //如果i大于65536,则每一次都获取十位和个位上的数字对应的字符。
q = i / 100;
// really: r = i - (q * 100);
r = i - ((q << 6) + (q << 5) + (q << 2)); //每次获得i的最后两位数
i = q;
buf [--charPos] = DigitOnes[r]; //存储r中在个位数集合中对应的字符
buf [--charPos] = DigitTens[r]; //存储r中在十位数集合中对应的字符
}
// Fall thru to fast mode for smaller numbers
// assert(i <= 65536, i);
for (;;) { //i<65536的情况
q = (i * 52429) >>> (16+3);
r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... //每次获得i的最后两位数
buf [--charPos] = digits [r];
i = q;
if (i == 0) break;
}
if (sign != 0) {
buf [--charPos] = sign; //设置符号
}
}
//定义sizeTable表示int中每个位数中最大的数,用于简便确定int数的长度。
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
//使用上面的sizeTable定义来确定int数的字符串表示长度。
static int stringSize(int x) {
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
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, len = s.length(); //i表示当前遍历的s的位数
int limit = -Integer.MAX_VALUE; //设置最小值为负的Integer的最大值
int multmin;
int digit;
if (len > 0) { //如果字符串长度大于0,则进行转换
char firstChar = s.charAt(0); //获取第一位字符
//在第一位字符小于'0'的情况下,判定是否含有符号'+'、'-'
if (firstChar < '0') { // Possible leading "+" or "-"
if (firstChar == '-') { //为负数的情况
negative = true;
limit = Integer.MIN_VALUE; //不能小于Integer的最小值
} else if (firstChar != '+') //不为'-'时,如果不为'+',则表示符号错误。
throw NumberFormatException.forInputString(s);
//如果字符串的长度等于1,且这个字符小于'0',则表示该字符串仅为一个符号,抛出异常
if (len == 1) // Cannot have lone "+" or "-"
throw NumberFormatException.forInputString(s);
i++;
}
multmin = limit / radix;
while (i < len) { //进行进制的转换
// 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);
}
result *= radix;
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
return negative ? result : -result; //根据符号返回正数还是负数
}
public static int parseInt(String s) throws NumberFormatException {
return parseInt(s,10);
}
public static Integer valueOf(String s, int radix) throws NumberFormatException {
return Integer.valueOf(parseInt(s,radix));
}
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
//内部字符缓存类
private static class IntegerCache {
//缓存的下界,-128,不可变
static final int low = -128;
//缓存上界,暂为null
static final int high;
static final Integer cache[]; //利用数组来缓存
static {
// high value may be configured by property
// 缓存上届,可以通过JVM属性来配置
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
//获取
if (integerCacheHighPropValue != null) {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
}
high = h;
//获取Integer中所有能保存的数据
cache = new Integer[(high - low) + 1];
int j = low;
//缓存所有Integer的数据
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127; //断言Integer缓存中的上届必须大于或等于127
if (i >= IntegerCache.low && i <= IntegerCache.high) //如果i在Integer缓存中,则直接取出
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i); //否则,直接创建一个实例
}
}