1.1 前言
Integer是int对应的包装类,它包含一个int类型的字段存储数据,并提供了多个基本操作,能在 int 类型和 String 类型之间互相转换。在Java5中,引入了自动装箱和自动拆箱功能,Java可根据上下文,自动进行转换,极大的简化了相关编程。
1.2 定义
public final class Integer extends Number implements Comparable<Integer>
从上述代码可以看出
- Integer类被final修饰,因此不能被继承。
- Integer类继承了Number类,因此可以调用longValue、floatValue、doubleValue等系列方法返回对应的类型的值。
- Integer类实现了Comparable接口,可以进行比较。
1.3 属性
private final int value;
私有属性,value用于保存int值。
1.4 构造方法
//直接将参数赋值给value属性 public Integer(int value) { this.value = value; } //参数为String类型,调用parseInt(String s,int radix)方法给value赋值,其中radix默认为10,即创建一个十进制的整数 public Integer(String s) throws NumberFormatException { this.value = parseInt(s, 10); }
1.5 核心方法
根据上述第二个构造方法可以知道,当传入一个String类型的参数时,会调用parseInt(String s,int radix)方法,因此接下来我们一起看一下这个方法,源代码如下
public static int parseInt(String s, int radix)
throws NumberFormatException
{
//字符串为空,则报异常
if (s == null) {
throw new NumberFormatException("null");
}
//其中MIN_RADIX=2,即如果radix<2,抛异常
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
//其中MIN_RADIX=36,即如果radix>36,抛异常
if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}
int result = 0;//最终转换的结果
boolean negative = false;//符号位判断,判断是否是‘-’号,如果是,将negative置为true
int i = 0, len = s.length();//设置初始位置和字符串长度
int limit = -Integer.MAX_VALUE;//设置最大边界,MAX_VALUE=2^31-1
int multmin;//最大边界值右移一位
int digit;
if (len > 0) {//字符串长度大于0,若小于零则抛出异常
char firstChar = s.charAt(0);//获取字符串第一个字符
if (firstChar < '0') { // 与'0'比较,若小于,则非数字
if (firstChar == '-') {//继续判断是否是'-'
negative = true;//如果是,则将negative 设置为true
limit = Integer.MIN_VALUE;//将limit设置为MIN_VALUE,其中MIN_VALUE=-2^31
} else if (firstChar != '+')
throw NumberFormatException.forInputString(s);//如果首字符既不是‘-’号,又不是‘+’号,则抛异常
if (len == 1) // Cannot have lone "+" or "-"
throw NumberFormatException.forInputString(s);//如果首字符只有一个符号,没有数字,则抛出异常
i++;//位置后移一位
}
multmin = limit / radix;//用于判断结果是否溢出
//下边的处理逻辑假设,,此时Integer ie = new Integer("324")
//首先i=0,取出"3",则digit=3,result = result-digit = -3
//i=1,取出"2",则digit=2,result = result*radix = -3*10 = -30,result = result-digit = -30-2 = -32
//i=2,取出"4",则dight =4,result = -32*10-4 =-324
while (i < len) {
// 将字符转换成对应进制的整数
digit = Character.digit(s.charAt(i++),radix);
//小于0,抛出异常
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
//result < multmin==>result<limit/radix==>result * radix<limit
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;//若是负数,则按照上边例子,result = -324,若为正数,则result =-(-324) = 324
}
接下来我们在看看valueOf()方法,Integer提供了三种valueOf方法,源码如下:
//调用parseInt(s,radix),获得一个int值,然后在调用valueOf(int i)方法 public static Integer valueOf(String s, int radix) throws NumberFormatException { return Integer.valueOf(parseInt(s,radix)); } //调用parseInt(s,10),获得一个int值,然后在调用valueOf(int i)方法 public static Integer valueOf(String s) throws NumberFormatException { return Integer.valueOf(parseInt(s, 10)); } //传入int值位于IntegerCache的成员变量low和high之间时,直接返回IntegerCache.cache[i + (IntegerCache.low)] //否则,新创建一个Integer对象 public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
在valueOf(int i)方法中用到了IntegerCache,因此我们在看一下IntegerCache,源码如下:
//IntegerCache是Integer的私有静态内部类 private static class IntegerCache { static final int low = -128;//设置缓存数组元素最小值 static final int high;//设置缓存数组元素最大值 static final Integer cache[];//定义一个Integer类型的数组 static { // high value may be configured by property int h = 127;//设置缓存元素最大值 //读取VM参数 String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue);//将配置值转换为int i = Math.max(i, 127);//将配置值与127进行比较,取最大者 // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1);//正整数能缓存的个数 } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1];//构造缓存数组,大小为256 int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++);//在数组下标为0-255的数组中预先将-128-127存入数组当中 // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {} }
从上述代码可以看出,当调用valueOf方法,如果参数的值在-127到128之间,则直接从缓存中返回一个已经存在的对象。如果参数的值不在这个范围内,则new一个Integer对象返回。
从上边的代码可以得出:parseInt方法返回的是基本类型int;valueOf方法返回Integer对象。
接下来我们再来看看将toString方法,源码如下:
public String toString() {
return toString(value);
}
public static String toString(int i) {
if (i == Integer.MIN_VALUE)
return "-2147483648";//如果等于Integer.MIN_VALUE,直接返回最小值的字符串形式
//返回一个正整数的位数,当i<0的时候返回的size数组在stringSize方法的基础上+1的目的是这一位用来存储负号
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] buf = new char[size];//创建一个字符数组
getChars(i, size, buf);//得到整数中的每一个字符
return new String(buf, true);
}
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
//该方法要求传入一个正整数,假设此时x=1000,那么因为他大于9,99,999,小于9999.所以他会返回9999在整型数组sizeTable中的下标”3″+1 = 4,因此返回一个正整数的位数
static int stringSize(int x) {
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
static void getChars(int i, int index, char[] buf) {
int q, r;
int charPos = index;
char sign = 0;
//如果i<0,sign记下它的符号“-”,同时将i转成整数
if (i < 0) {
sign = '-';
i = -i;
}
//当i >= 65536的时候每一次获取两位的char值。
while (i >= 65536) {
q = i / 100;
// really: r = i - (q * 100);
r = i - ((q << 6) + (q << 5) + (q << 2));//使用移位操作快速计算出q*100,该表达式可以改为i-q*2^6 - q*2^5 - q*2^2= i-64q-32q-4q= i-100q。
i = q;
buf [--charPos] = DigitOnes[r];//取数字r%10的结果
buf [--charPos] = DigitTens[r];//取数字r/10的结果
}
// 当 i <= 65536的时候每次只获取一位的char值
for (;;) {
q = (i * 52429) >>> (16+3);//相当于q=i/10
r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ...
buf [--charPos] = digits [r];
i = q;
if (i == 0) break;
}
if (sign != 0) {
buf [--charPos] = sign;//如果是负数加上符号位
}
}
//100以内的数字除以10的结果(取整), //比如取DigitTens[78],返回的是数字7 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', } ; //100以内的数字对10取模的结果, //比如取DigitTens[78],返回的8 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', } ;
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'
};
1.6实现Number的方法
源码如下:
public byte byteValue() {
return (byte)value;
}
public short shortValue() {
return (short)value;
}
public int intValue() {
return value;
}
public long longValue() {
return (long)value;
}
public float floatValue() {
return (float)value;
}
public double doubleValue() {
return (double)value;
}
1.7关于Integer的面试题
Integer a = new Integer(127);
Integer b = new Integer(127);
Integer c = new Integer(128);
Integer d = new Integer(128);
Integer e = 128; 反编译过来之后是Integer.valueOf(128)
Integer f = 128; 反编译过来之后是Integer.valueOf(128)
Integer i= 127; 反编译过来之后是Integer.valueOf(127)
Integer j= 127; 反编译过来之后是Integer.valueOf(127)
System.out.println(a==b);//false
System.out.println(a.equals(b));//true
System.out.println(c==d);//false
System.out.println(c.equals(d));//true
System.out.println(e==f);//false
System.out.println(e.equals(f));//true
System.out.println(i==j);//true
System.out.println(i.equals(j));//true
筱虾米 
![[爱了]](/js/img/d1.gif)
![[尴尬]](/js/img/d16.gif)