平平无奇Integer,为啥经常问

620 阅读2分钟

最近在面试的时候,有好几个面试官问了我 Integer.valueOf 这个方法。这个方法之前确实没研究过,所以专门记录一下。

Integer.valueOf方法有三个重载,分别是

  • Integer.valueOf(String s, int radix)
  • Integer.valueOf(String s)
  • Integer.valueOf(int i)

前两个方法都会调用到最后这个方法来,所以直接看参数最多的一个就好了。

    //首先解释一下两个参数的含义,第一个参数是待转换的字符串,第二个参数为字符串的进制。
    public static Integer valueOf(String s, int radix) throws NumberFormatException {
        return Integer.valueOf(parseInt(s,radix));
    }

也就是如果我们需要转换10进制的 '123' 的话,输入就是 ("123",10), 如果需要转换2进制的数字,输入就是("10101101",2)

进入方法之后首先会进入parseInt方法。这个方法会将输入转换为int结果。首先来分析一下:

    public static int parseInt(String s, int radix)
                throws NumberFormatException
    {
		//检验一下是否为空
        if (s == null) {
            throw new NumberFormatException("null");
        }
		//校验一下进制是否在范围内,最小为2进制,最大为36进制
        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");
        }
		//下面运算的时候全部先转为负数运算,这样方便判断溢出
        boolean negative = false;
        int i = 0, len = s.length();
        int limit = -Integer.MAX_VALUE;

        if (len > 0) {
            char firstChar = s.charAt(0);
            if (firstChar < '0') { // Possible leading "+" or "-"
                if (firstChar == '-') {
                    negative = true;
                    limit = Integer.MIN_VALUE;
                } else if (firstChar != '+') {
                    throw NumberFormatException.forInputString(s, radix);
                }

                if (len == 1) { // Cannot have lone "+" or "-"
                    throw NumberFormatException.forInputString(s, radix);
                }
                i++;
            }
            //先计算好中间值
            int multmin = limit / radix;
            int result = 0;
            while (i < len) {
                //Character.digit方法作用就是将字符转换为数字
                int digit = Character.digit(s.charAt(i++), radix);
                //此处有两个判断,1.如果字符非法,报异常
                //2.如果result在没有进位时便超过了multmin,那么进位后必然溢出,报异常
                if (digit < 0 || result < multmin) {
                    throw NumberFormatException.forInputString(s, radix);
                }
                result *= radix;
                //此处还有一个溢出判断,判断result添加digit后是否会溢出,如果溢出报异常
                if (result < limit + digit) {
                    throw NumberFormatException.forInputString(s, radix);
                }
                result -= digit;
            }
            //判断是否为负数,将实际结果转变过来
            return negative ? result : -result;
        } else {
            throw NumberFormatException.forInputString(s, radix);
        }
    }

整个 parseInt 方法逻辑还是比较清晰的。理解一下应该没啥难度。

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

在转换为int之后,Integer类还会对int进行一个对象的包装。这个地方涉及到Integer的缓存。在jvm启动的时候,默认情况会将-128 - 127中间的数字先缓存在jvm中,这样用到的话便可以直接调用。

那么到这儿的话Integer.valueOf方法解析到这儿就完了。

说实话看了一遍还是不太理解为啥面试要问这个(^_^)v