【Java】JDK源码分析——Integer

    '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',

    } ;



// 该数组表示n位数字能表示的最大值,n从1开始

// 如:1位数字最大的是9,2位数字最大的是99…

// 该数组在stringSize方法中使用

final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,

                                  99999999, 999999999, Integer.MAX_VALUE };



// 用于保存int的数值

private final int value;



// int型数占的位数

@Native public static final int SIZE = 32;



// 一个int数占的字节

public static final int BYTES = SIZE / Byte.SIZE;



// 用于序列化

@Native private static final long serialVersionUID = 1360826667806852920L;



[]( )2.静态内部类IntegerCache

-------------------------------------------------------------------------------------



该类用于提供一定范围的Integer对象的缓存。  

**Integer.java中的相关代码:**



private static class IntegerCache {

    static final int low = -128; // 缓存提供的最小的值:-128

    static final int high; // 缓存提供最大的值

    static final Integer cache[]; // 用于存储缓存数值的数组



    // 静态代码块初始化

    static {

        // 暂时设置缓存提供最大的值为127

        int h = 127;

        // 从虚拟机参数中读取缓存可以提供的最大值

        String integerCacheHighPropValue =

            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");

        // 若参数在虚拟机中存在,即不为空

        if (integerCacheHighPropValue != null) {

            try {

                // 调用parseInt方法,将String转换为int数值

                int i = parseInt(integerCacheHighPropValue);

                // 和127比较,取其中最大的

                i = Math.max(i, 127);



                // 和Integer.MAX_VALUE - (-low) -1比较,取其中最小的

                // 因为数组的最大长度不能超过Integer.MAX_VALUE

                // 所以Integer.MAX_VALUE - (-low) -1表示最小值为-128时,

				// 可以取到的最大值

                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);

            } catch( NumberFormatException nfe) {

                // If the property cannot be parsed into an int, ignore it.

            }

        }

        // 设置缓存提供最大的值为h

        high = h;



        // 根据最大值和最小值计算数组长度,创建数组

        cache = new Integer[(high - low) + 1];

        int j = low;

        // 循环填充数据,数组位置从0开始,数值从-128开始

        for(int k = 0; k < cache.length; k++)

            cache[k] = new Integer(j++);



        // 假设缓存的最大值大于等于127

        assert IntegerCache.high >= 127;

    }



    // 私有化构造方法

    private IntegerCache() {}

}



[]( )3.构造方法

------------------------------------------------------------------------



### []( )1)参数为int



**Integer.java中的相关代码:**



public Integer(int value) {

	// 保存到全局变量

    this.value = value;

}



### []( )2)参数为String



**Integer.java中的相关代码:**



public Integer(String s) throws NumberFormatException {

	// 调用parseInt方法,将字符串按十进制解析成int数值

    this.value = parseInt(s, 10);

}



[]( )4\. parseInt方法

--------------------------------------------------------------------------------



将字符串型整数解析成int型数值。  

**Integer.java中的相关代码:**



public static int parseInt(String s) throws NumberFormatException {

	// 调用重载方法,按照十进制进行解析

    return parseInt(s,10);

}



调用了重载的parseInt方法。  

将指定进制的字符串型整数解析成int型的数。  

**Integer.java中的相关代码:**



public static int parseInt(String s, int radix)

            throws NumberFormatException

{

    /*

     * 注意: 在IntegerCache完成初始化之前的虚拟机初始化阶段

     * 可以使用parseInt方法,注意不要使用valueOf方法。

     */



    // 若字符串为空,则抛出异常

    if (s == null) {

        throw new NumberFormatException("null");

    }



    // 若数值的进制小于最小的进制数2,则抛出异常

    // Character.MIN_RADIX = 2

    if (radix < Character.MIN_RADIX) {

        throw new NumberFormatException("radix " + radix +

                                        " less than Character.MIN_RADIX");

    }



    // 若数值的进制大于最大的进制数36,则抛出异常

    // Character.MAX_RADIX = 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(); // len表示字符串长度,i为指针

    int limit = -Integer.MAX_VALUE; // 表示数值最大不能超过的范围

    int multmin; // 每次进行乘以进制数之前,不能超过的范围,超过会发生溢出

    int digit; // 用于承接字符串中每一位的数值



    // 若长度大于0

    if (len > 0) {

        // 获取首位字符

        char firstChar = s.charAt(0);

        // 小于’0’,说明可能为‘+’或‘-’

        if (firstChar < '0') {

            // 若为负号

            if (firstChar == '-') {

                // 设置标志位为负

                negative = true;

                // 设置最大范围

                limit = Integer.MIN_VALUE;

            } else if (firstChar != '+') // 若不是加号,说明为其它字符,则抛出异常

                throw NumberFormatException.forInputString(s);



            //若长度为1,说明只有符号,没有数值,则抛出异常

            if (len == 1)

                throw NumberFormatException.forInputString(s);

            // 指针指向下一位

            i++;

        }

        // 计算乘以进制数前数值的最大范围

        multmin = limit / radix;



        // 计算方法:对不同进制的字符串,先用result乘以字符串本身的进制,

        // 1)用result乘以字符串本身的进制数,保存到result中

        // 2)从前向后依次取字符串中的字符,转换为十进制对应的数值,

		//    累加到result上

		// 3)循环执行1)和2),遍历所有字符,最后的结果就是对应的int型数。

		// 同时为了防止在最大值出发生意外,采用负向累加的方法

		// 即:对于正数,每次减去字符表示的数值,再乘以进制数,最后进行

		// 符号调整。负数每次加上字符表示的数值,再乘以进制数,因为是负数,

		// 所以最后不调整符号。



		// 循环

        while (i < len) {

            // 获取字符,指针指向下一位

            // 调用Character的digit方法

            // 该方法会返回在指定进制下字符表示的十进制数

            digit = Character.digit(s.charAt(i++),radix);

            // 若返回的数小于0,则抛出异常

            if (digit < 0) {

                throw NumberFormatException.forInputString(s);

            }

            // 若超过乘以进制数前数值的最大范围

            // 说明乘以进制数后会溢出,因此抛出异常

            // 因为两个数都是负数,所以用<比较

            if (result < multmin) {

                throw NumberFormatException.forInputString(s);

            }

            // 乘以进制数,并保存到result中

            result *= radix;



            // 预先判断rusult减去字符对应的十进制数后会不会

            // 超过最大值范围,超过则抛异常。

            // 正常因该为result-digit<limit,为了防止result-digit溢出

            // 所以digit移到了右边

            if (result < limit + digit) {

                throw NumberFormatException.forInputString(s);

            }

            // 减去digit,因为result为负数,所以相当于反向增大

            result -= digit;

        }

    } else { // 若字符串长度等于0,则抛出异常

        throw NumberFormatException.forInputString(s);

    }

    // 若是负数,直接返回,若是正数,则调整符号再返回

    return negative ? result : -result;

}



[]( )5\. parseUnsignedInt方法

----------------------------------------------------------------------------------------



将String按照无符号十进制整数进行解析。  

**Integer.java中的相关代码:**



public static int parseUnsignedInt(String s) throws NumberFormatException {

	// 调用了重载方法,按照十进制进行解析

    return parseUnsignedInt(s, 10);

}



调用了重载的parseUnsignedInt方法。  

将指定进制的字符串型无符号整数解析成int型的数。  

**Integer.java中的相关代码:**



public static int parseUnsignedInt(String s, int radix)

            throws NumberFormatException {

    // 若字符串为空,则抛出异常

    if (s == null)  {

        throw new NumberFormatException("null");

    }



    // 获取字符串长度

    int len = s.length();

    // 若长度大于0

    if (len > 0) {

        // 获取首位的字符

        char firstChar = s.charAt(0);

        // 如果是减号,则抛出异常,因为是无符号型整数

        if (firstChar == '-') {

            throw new

                NumberFormatException(String.format("Illegal leading minus sign " +

                                                   "on unsigned string %s.", s));

        } else {// 若不是减号

            // 先判断符号位是否被占用

			// 即是否可以按照有符号情况的处理



            // 若长度小于等于5或十进制下长度小于等于9

            // 小于等于5是因为在int的数值范围内同时不占用符号位

			// 只能有5个最大进制——36进制的字符

			// 如果为10进制,满足范围要求和不占用符号位条件下

			// 只能有9个十进制的字符

            if (len <= 5 || (radix == 10 && len <= 9) ) {

                // 满足要求,可以按有符号情况进行处理

                // 调用parseInt处理 

                return parseInt(s, radix);

            } else { // 若不能按照有符号数进行处理

                // 调用Long的parseLong处理

                long ell = Long.parseLong(s, radix);

                // 若高32位为0,说明没有超过int的32位范围

                if ((ell & 0xffff_ffff_0000_0000L) == 0) {

                    // 进行类型转换,返回

                    return (int) ell;

                } else { // 若高32位不为0,说明有溢出,则抛出异常

                    throw new

                        NumberFormatException(String.format("String value %s exceeds " +"range of unsigned int.", s));

                }

            }

        }

    } else { // 长度小于等于0,则抛出异常

        throw NumberFormatException.forInputString(s);

    }

}



[]( )6\. valueOf方法

-------------------------------------------------------------------------------



将String类型的数转换为Integer对象。



### []( )1)参数为String



#### []( )指定进制数:



**Integer.java中的相关代码:**



public static Integer valueOf(String s, int radix) throws NumberFormatException {

	// 调用parseInt解析成int数值

	// 再调用重载方法,对int数值包装成Integer对象

    return Integer.valueOf(parseInt(s,radix));

}



#### []( )不指定进制数:



**Integer.java中的相关代码:**



public static Integer valueOf(String s) throws NumberFormatException {

	// 调用parseInt解析成int数值,默认10进制

	// 再调用重载方法,对int数值包装成Integer对象

    return Integer.valueOf(parseInt(s, 10));

}



### []( )2)参数为int



**Integer.java中的相关代码:**



public static Integer valueOf(int i) {

	// 若参数满足缓存的数值范围

    if (i >= IntegerCache.low && i <= IntegerCache.high)

        // 在缓存中查找,返回

        return IntegerCache.cache[i + (-IntegerCache.low)];

    // 缓存中没有,则创建新对象,返回

    return new Integer(i);

}



[]( )7\. byteValue方法

---------------------------------------------------------------------------------



获取当前数值对应的byte型数值。  

**Integer.java中的相关代码:**



public byte byteValue() {

	// 类型转换,返回

    return (byte)value;

}



[]( )8\. shortValue方法

----------------------------------------------------------------------------------



获取当前数值对应的short型数值。  

**Integer.java中的相关代码:**



public short shortValue() {

	// 类型转换,返回

    return (short)value;

}



[]( )9\. intValue方法

--------------------------------------------------------------------------------



获取当前数值对应的int型数值。  

**Integer.java中的相关代码:**



public int intValue() {

	// 直接返回

    return value;

}



[]( )10\. longValue方法

----------------------------------------------------------------------------------



获取当前数值对应的long型数值。  

**Integer.java中的相关代码:**



public long longValue() {

	// 类型转换,返回

    return (long)value;

}



[]( )11\. floatValue方法

-----------------------------------------------------------------------------------



获取当前数值对应的float型数值。  

**Integer.java中的相关代码:**



public float floatValue() {

	// 类型转换,返回

    return (float)value;

}



[]( )12\. doubleValue方法

------------------------------------------------------------------------------------



获取当前数值对应的double型数值。  

**Integer.java中的相关代码:**



public double doubleValue() {

	// 类型转换,返回

    return (double)value;

}



[]( )13\. toString方法

---------------------------------------------------------------------------------



将Integer对象转换为String对象。



### []( )1)无参数



**Integer.java中的相关代码:**



public String toString() {

	// 调用重载方法

    return toString(value);

}



### []( )2)参数为int



只能将数值转换为十进制表示的字符串。  

**Integer.java中的相关代码:**



public static String toString(int i) {

	// 若为最小值,直接返回"-2147483648"

    if (i == Integer.MIN_VALUE)

        return "-2147483648";

    // 调用stringSize方法获取数字的长度

    // 小于0时,因为有负号,所以加一

    // 详解在a)处

    int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);

    // 根据长度创建字符数组

    char[] buf = new char[size];

    // 调用getChars方法,对字符数组进行填充

    // 详解在b)处

    getChars(i, size, buf);

    // 根据字符数组的内容,创建新的字符串

    return new String(buf, true);

}



#### []( )a)stringSize方法



获取一个数字的长度。  

**Integer.java中的相关代码:**



static int stringSize(int x) {

	// 循环,判断该数是否i位数的最大值

    for (int i=0; ; i++)

        // 若该数大于i位数的最大值

        if (x <= sizeTable[i])

            // 因为i是从0开始,但没有0位数,

			// 数字最少1位,所以要加1。

            return i+1;

}



#### []( )b)getChars方法



该方法用于将数字填充到字符数组中。  

**Integer.java中的相关代码:**



static void getChars(int i, int index, char[] buf) {

    int q, r; // q,r用于承接个位、十位、百位、千位…的数字

    int charPos = index; // 指针,从后向前填充字符数组

    char sign = 0; // 用于保存数字的符号



    // 若数值小于0

    if (i < 0) {

        // 设置符号为负号

        sign = '-';

        // 将负数变成正数

        i = -i;

    }



    // 对于大于65536的数

    // 先通过迭代,每次向字符数组中填充两个字符

    while (i >= 65536) {

        q = i / 100;

        // 该操作实际效果等同于r = i - (q * 100);

        // r实际上就是数值的后两位

        r = i - ((q << 6) + (q << 5) + (q << 2));

        // i此时变成了去除了后两位数字的数

        i = q;

        // 从数组中查找,填充字符数组,指针向前移动

        buf [--charPos] = DigitOnes[r];

        buf [--charPos] = DigitTens[r];

    }



    // 对于小于65536的数字

	// 每次向字符数组中填充一个字符

    for (;;) {

        // 该操作相当于q = i /10;

        q = (i * 52429) >>> (16+3);

        // 该操作相当于r = i-(q*10);

        r = i - ((q << 3) + (q << 1));

        // 经过上面两部操作,r的值为i的最后一位

        // 查找数组,填充字符数组,指针向前移动

        buf [--charPos] = digits [r];

        // 此时i变为去除最后一位数字的数

        i = q;

        // 若i为0,说明没有数字可以填充,跳出循环

        if (i == 0) break;

    }

    // 若sign不为0,说明为负数

    if (sign != 0) {

        // 填充负号

        buf [--charPos] = sign;

    }

}



### []( )3)参数为int



支持将数值转换为不同进制表示的字符串。  

**Integer.java中的相关代码:**



public static String toString(int i, int radix) {

	// 若进制数大于最大进制数36或小于最小进制数2

    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)

        // 则默认进制数为10

        radix = 10;



    // 若进制为10

    if (radix == 10) {

        // 调用重载的toString方法处理

        return toString(i);

    }



    // 创建字符数组

    // 长度最长时为二进制情况下,共32位,因为可能有负号

    // 所以加1,共33位

    char buf[] = new char[33];

    // 标志位,用于判断数值的正负

    boolean negative = (i < 0);

    // 指针,从后向前

    int charPos = 32;



    // 若为正数,则将正值变成负值

    // 这样处理,可以防止正向溢出

    if (!negative) {

        i = -i;

    }



    // 当负的数值小于等于负的进制数

    while (i <= -radix) {

        // i除以radix取余,再将余数变成正数,查找数组

        // 填充到字符数组,指针向前移动

        buf[charPos--] = digits[-(i % radix)];

        // 实际效果相当于去掉i小于进制数radix的部分

        i = i / radix;

    }

    // 填充最后一个字符

    buf[charPos] = digits[-i];



    // 若为负数

    if (negative) {

        // 填充负号,指针向前移动

        buf[--charPos] = '-';

    }



    // 根据字符数组的内容和长度,创建新字符串

    return new String(buf, charPos, (33 - charPos));

}



[]( )14\. hashCode方法

---------------------------------------------------------------------------------



获取当前对象的哈希值。  

**Integer.java中的相关代码:**



@Override

public int hashCode() {

	// 调用静态方法hashCode

    return Integer.hashCode(value);

}



调用静态方法hashCode。  

**Integer.java中的相关代码:**



public static int hashCode(int value) {

	// 直接返回数值

    return value;

}



[]( )15\. equals方法

-------------------------------------------------------------------------------



比较两个Integer对象的值是否相等。  

**Integer.java中的相关代码:**



public boolean equals(Object obj) {

	// 若为Integer对象

    if (obj instanceof Integer) {

        // 比较两个对象的值是否相等

        return value == ((Integer)obj).intValue();

    }

    // 若不是Integer对象,返回false

    return false;

}



[]( )16\. getInteger方法

-----------------------------------------------------------------------------------



从系统变量中读取Integer数值。



### []( )1)不指定默认值



**Integer.java中的相关代码:**



public static Integer getInteger(String nm) {

	// 调用重载方法,若获取不到,则返回为空

	// 详解在3)处

    return getInteger(nm, null);

}



### []( )2)指定默认值



**Integer.java中的相关代码:**



public static Integer getInteger(String nm, int val) {

	// 调用重载方法,若获取不到,则返回为空

	// 详解在3)处

    Integer result = getInteger(nm, null);

    // 若返回值为空,则将默认值包装成Integer对象,返回

    // 若返回值不为空,则直接返回

    return (result == null) ? Integer.valueOf(val) : result;

}



### []( )3)重载的getInteger方法



**Integer.java中的相关代码:**



public static Integer getInteger(String nm, Integer val) {

	// 用于保存获取的系统变量

    String v = null;

    try {

        // 获取系统变量

        v = System.getProperty(nm);

    } catch (IllegalArgumentException | NullPointerException e) {

    }

    // 若系统变量不为空

    if (v != null) {

        try {

            // 将系统变量进行解码成Integer对象,返回

            return Integer.decode(v);

        } catch (NumberFormatException e) {

        }

    }

    // 若系统变量不存在,则返回默认值

    return val;

}



[]( )17\. decode方法

-------------------------------------------------------------------------------



将字符串解码成Integer对象。  

该方法支持带有进制标识符(如:0x,#)的8、10、16进制的字符串,但是字符串中不能有空格。  

**Integer.java中的相关代码:**



public static Integer decode(String nm) throws NumberFormatException {

	// 默认进制为10

    int radix = 10;

    // 指针从0开始

    int index = 0;

    // 判断正负数的标志位,默认正数

    boolean negative = false;

    // 用于保存解码后的结果

    Integer result;



    // 若长度为0,抛出异常

    if (nm.length() == 0)

        throw new NumberFormatException("Zero length string");

    // 获取首位字符

    char firstChar = nm.charAt(0);

    // 若为负号

    if (firstChar == '-') {

        // 设置标志位,指针向后移动

        negative = true;

        index++;

    // 若为正号

    } else if (firstChar == '+')

        // 指针向后移动

        index++;



    // 对进制标识符进行处理

    // 若以“0x”或“0X”开头

    if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {

        // 指针后移两位

        index += 2;

        // 设置进制为16进制

        radix = 16;

    } // 若以“#”开头

    else if (nm.startsWith("#", index)) {

        // 指针向后移动

        index ++;

        // 设置进制为16进制

        radix = 16;

    } // 若以“0”开头,同时不是只有一个0

    else if (nm.startsWith("0", index) && nm.length() > 1 + index) {

        // 指针向后移动

        index ++;

        // 设置进制为8进制

        radix = 8;

    }



    // 若在进制标识符后出现正负号,则抛出异常

    if (nm.startsWith("-", index) || nm.startsWith("+", index))

        throw new NumberFormatException("Sign character in wrong position");



    try {

        // 截取数值部分,调用valueOf方法进行解析

        result = Integer.valueOf(nm.substring(index), radix);

        // 对数值的正负进行调整

        result = negative ? Integer.valueOf(-result.intValue()) : result;

最后

由于文案过于长,在此就不一一介绍了,这份Java后端架构进阶笔记内容包括:Java集合,JVM、Java并发、微服务、SpringNetty与 RPC 、网络、日志 、Zookeeper 、Kafka 、RabbitMQ 、Hbase 、MongoDB、Cassandra 、Java基础、负载均衡、数据库、一致性算法、Java算法、数据结构、分布式缓存等等知识详解。

image

本知识体系适合于所有Java程序员学习,关于以上目录中的知识点都有详细的讲解及介绍,掌握该知识点的所有内容对你会有一个质的提升,其中也总结了很多面试过程中遇到的题目以及有对应的视频解析总结。

image

image

tChar == ‘+’)

        // 指针向后移动

        index++;



    // 对进制标识符进行处理

    // 若以“0x”或“0X”开头

    if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {

        // 指针后移两位

        index += 2;

        // 设置进制为16进制

        radix = 16;

    } // 若以“#”开头

    else if (nm.startsWith("#", index)) {

        // 指针向后移动

        index ++;

        // 设置进制为16进制

        radix = 16;

    } // 若以“0”开头,同时不是只有一个0

    else if (nm.startsWith("0", index) && nm.length() > 1 + index) {

        // 指针向后移动

        index ++;

        // 设置进制为8进制

        radix = 8;

    }



    // 若在进制标识符后出现正负号,则抛出异常

    if (nm.startsWith("-", index) || nm.startsWith("+", index))

        throw new NumberFormatException("Sign character in wrong position");



    try {

        // 截取数值部分,调用valueOf方法进行解析

        result = Integer.valueOf(nm.substring(index), radix);

        // 对数值的正负进行调整

        result = negative ? Integer.valueOf(-result.intValue()) : result;

最后

由于文案过于长,在此就不一一介绍了,这份Java后端架构进阶笔记内容包括:Java集合,JVM、Java并发、微服务、SpringNetty与 RPC 、网络、日志 、Zookeeper 、Kafka 、RabbitMQ 、Hbase 、MongoDB、Cassandra 、Java基础、负载均衡、数据库、一致性算法、Java算法、数据结构、分布式缓存等等知识详解。

[外链图片转存中…(img-v9LHvSzK-1714497835121)]

本知识体系适合于所有Java程序员学习,关于以上目录中的知识点都有详细的讲解及介绍,掌握该知识点的所有内容对你会有一个质的提升,其中也总结了很多面试过程中遇到的题目以及有对应的视频解析总结。

[外链图片转存中…(img-Izg5wFq7-1714497835122)]

[外链图片转存中…(img-pT6HIhvO-1714497835123)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值