一文带你搞定Integer

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  
 

未经允许不得转载:博客 » 一文带你搞定Integer

赞 (0)

评论 0

评论前必须登录!

登陆 注册