一 简介

Integer是int基本类型的包装类,同样继承了Number类,实现了Comparable接口,String类中的一些转化方法就使用了Integer类中的一些API,且fianl修饰不可继承:

  1. public final class Integer extends Number implements Comparable<Integer> {

Number传送门

Long类源码和Integer类源力基本相同,大部分API是一样的逻辑!

二 源码解析

Integer类API比较多也比较重要,分开几个部分解析:

1 属性

  1. // 包装类的int类型值
  2. private final int value;
  3. //两个被废弃的构造器,官方推荐valueOf形式
  4. @Deprecated(since="9")
  5. public Integer(int value) {
  6. this.value = value;
  7. }
  8. @Deprecated(since="9")
  9. public Integer(String s) throws NumberFormatException {
  10. this.value = parseInt(s, 10);
  11. }
  12. // int最小值,
  13. @Native public static final int MIN_VALUE = 0x80000000;
  14. //int最大值, int 范围 - 2^{31} 到2^{31}-1之间的整数即: -2147483648 ~2147483647
  15. @Native public static final int MAX_VALUE = 0x7fffffff;
  16. // 表示二进制补码形式的int值的比特数比,32
  17. @Native public static final int SIZE = 32;
  18. //字节数常量,4
  19. public static final int BYTES = SIZE / Byte.SIZE;
  20. // Class类实例
  21. public static final Class<java.lang.Integer> TYPE = (Class<java.lang.Integer>) Class.getPrimitiveClass("int");
  22. //将数字表示为字符串的所有可能字符,因为int支持从2进制到36进制,所以这里需要有36个字符才能表示所有不同进制的数字
  23. static final char[] digits = {
  24. '0' , '1' , '2' , '3' , '4' , '5' ,
  25. '6' , '7' , '8' , '9' , 'a' , 'b' ,
  26. 'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
  27. 'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
  28. 'o' , 'p' , 'q' , 'r' , 's' , 't' ,
  29. 'u' , 'v' , 'w' , 'x' , 'y' , 'z'
  30. };
  31. /**
  32. * DigitTens和DigitOnes两个数组主要用于获取0到99之间某个数的十位和个位字符,
  33. * 比如48,通过DigitTens数组直接取出来十位为4,而通过DigitOnes数组取出来个位为8
  34. */
  35. static final byte[] DigitTens = {
  36. '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
  37. '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
  38. '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
  39. '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
  40. '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
  41. '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
  42. '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
  43. '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
  44. '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
  45. '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
  46. } ;
  47. static final byte[] DigitOnes = {
  48. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  49. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  50. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  51. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  52. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  53. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  54. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  55. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  56. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  57. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  58. } ;
  59. /**
  60. * sizeTable数组主要用在判断一个int型数字(只能判断正数)对应字符串的长度。比如相关的方法如下,这种方法可以高效得到对应字符串长度,避免了使用除法或求余等操作
  61. * jdk8中并没有使用这个数组,直接用的while循环计算,正负数都可以判断,返回长度算上了符号长度,即-1的长度是2
  62. * static int stringSize(int x) {
  63. * for (int i=0; ; i++)
  64. * if (x <= sizeTable[i])
  65. * return i+1; //直接通过判断返回长度
  66. * }
  67. */
  68. static final int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
  69. 99999999, 999999999, java.lang.Integer.MAX_VALUE };

2 toString方法(重点,需要用到上面三个byte矩阵数组)

  1. //实例方法
  2. public String toString() {
  3. return toString(value);
  4. }
  5. /**
  6. * 返回第一个参数的字符串形式,第二个参数为进制的基数,二进制10进制十六进制等
  7. */
  8. public static String toString(int i, int radix) {
  9. //如果基数小于2或者大于36,则默认使用10进制转换
  10. if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
  11. radix = 10;
  12. //返回int类型参数十进制形式字符串
  13. if (radix == 10) {
  14. return toString(i);
  15. }
  16. if (COMPACT_STRINGS) {
  17. byte[] buf = new byte[33];
  18. boolean negative = (i < 0);
  19. int charPos = 32; //从数组最后一位开始添加
  20. if (!negative) {
  21. i = -i;
  22. }
  23. /**
  24. * 按进制处理,求余digits从获取对应字符串,比如 -15转为16进制 -15 % 16 = 15 ,digits 中15 为 f
  25. */
  26. while (i <= -radix) {
  27. buf[charPos--] = (byte)digits[-(i % radix)];
  28. i = i / radix;
  29. }
  30. buf[charPos] = (byte)digits[-i];
  31. if (negative) {
  32. buf[--charPos] = '-';
  33. }
  34. return StringLatin1.newString(buf, charPos, (33 - charPos));
  35. }
  36. return toStringUTF16(i, radix);
  37. }
  38. /**
  39. * 返回int类型参数十进制形式字符串
  40. */
  41. public static String toString(int i) {
  42. int size = stringSize(i);
  43. if (COMPACT_STRINGS) { //jvm是否开启字符串压缩
  44. byte[] buf = new byte[size];
  45. getChars(i, size, buf); //将int参数字符串放入byte数组中
  46. return new String(buf, LATIN1);
  47. } else {
  48. byte[] buf = new byte[size * 2];
  49. StringUTF16.getChars(i, size, buf);// 思路与上面getChars一样,放进数组的时候会进行高低位两个byte放
  50. return new String(buf, UTF16);
  51. }
  52. }
  53. //返回给定int值的字符串表示长度
  54. static int stringSize(int x) {
  55. int d = 1;
  56. if (x >= 0) {
  57. d = 0;
  58. x = -x; //整数改为负数,统一用负数判断大小
  59. }
  60. int p = -10;//判断大小基数,大于-10,一位,否则再判断大于-100,两位等
  61. for (int i = 1; i < 10; i++) { // 判断9次
  62. if (x > p)
  63. return i + d;
  64. p = 10 * p;
  65. }
  66. return 10 + d; //超过九位数,返回int最大的长度,10或者11位
  67. }
  68. //将int参数字符串放入byte数组中
  69. static int getChars(int i, int index, byte[] buf) {
  70. int q, r;
  71. int charPos = index; //数组开始位置坐标,传入的是数组大小,从 --index 最后一位往前添加数据
  72. boolean negative = i < 0;
  73. if (!negative) { //正数转化为负数
  74. i = -i;
  75. }
  76. /**
  77. * 每次取后两位数,将最后两位字符添加到数组中,比如: -2358
  78. * q=-23 整数相除,结果都为整数
  79. * r=-2300-(-2358)=58
  80. * 从DigitOnes和DigitTens中找出第58个字符,即8和5依次加入数组中
  81. */
  82. while (i <= -100) {
  83. q = i / 100;
  84. r = (q * 100) - i;
  85. i = q; // 每次增大100,即去掉后两位数,继续循环处理,直到成为两位数以内
  86. buf[--charPos] = DigitOnes[r];
  87. buf[--charPos] = DigitTens[r];
  88. }
  89. // 处理剩余的两位数,比如: -23 q=-2, r= 3
  90. q = i / 10;
  91. r = (q * 10) - i;
  92. buf[--charPos] = (byte)('0' + r); // 转换为byte存储
  93. if (q < 0) {
  94. buf[--charPos] = (byte)('0' - q);
  95. }
  96. //处理符号位
  97. if (negative) {
  98. buf[--charPos] = (byte)'-';
  99. }
  100. return charPos;
  101. }
  102. //按照一个字符占用两个byte处理
  103. private static String toStringUTF16(int i, int radix) {
  104. byte[] buf = new byte[33 * 2];
  105. boolean negative = (i < 0);
  106. int charPos = 32;
  107. if (!negative) {
  108. i = -i;
  109. }
  110. //按进制处理,求余digits从获取对应字符串,比如 -15转为16进制 -15 % 16 = 15 ,digits 中15 为 f
  111. while (i <= -radix) {
  112. StringUTF16.putChar(buf, charPos--, digits[-(i % radix)]);
  113. i = i / radix;
  114. }
  115. StringUTF16.putChar(buf, charPos, digits[-i]);
  116. if (negative) {
  117. StringUTF16.putChar(buf, --charPos, '-');
  118. }
  119. return StringUTF16.newString(buf, charPos, (33 - charPos));
  120. }

3 to系列其他方法

  1. //1.8新增方法,返回无符号参数int的十进制字符串,注意: 两个新增方法实现逻辑都在Long类中,Unsigned方法参数如果是有符号的(即负数),结果都会有问题
  2. public static String toUnsignedString(int i) {
  3. return Long.toString(toUnsignedLong(i));
  4. }
  5. /**
  6. * 将无符号int转换为long类型,负数不报错结果不正确
  7. * @since 1.8
  8. */
  9. public static long toUnsignedLong(int x) { return ((long) x) & 0xffffffffL; }
  10. //1.8新增方法: 根据进制基数,返回无符号int参数号的字符串形式,新增方法,功能与下面三种方法一样,只不过还支持10进制等进制
  11. public static String toUnsignedString(int i, int radix) {
  12. return Long.toUnsignedString(toUnsignedLong(i), radix);
  13. }
  14. // 转换为16进制字符串
  15. public static String toHexString(int i) {
  16. return toUnsignedString0(i, 4);
  17. }
  18. // 转换为8进制字符串
  19. public static String toOctalString(int i) {
  20. return toUnsignedString0(i, 3);
  21. }
  22. // 转换为2进制字符串
  23. public static String toBinaryString(int i) {
  24. return toUnsignedString0(i, 1);
  25. }
  26. // 将无符号整数转换为String,私有方法,只支持2,8,16三种进制转换, 负数不报错但结果不正确
  27. private static String toUnsignedString0(int val, int shift) {
  28. /**
  29. * 32减去numberOfLeadingZeros, 表示实际表示此数字只需要的位数。
  30. * 比如10的二进制补码是0000 0000 0000 0000 0000 0000 0000 1010,
  31. * 它实际只需要1010这4位数字就可以代表10. 所以10的mag就是4
  32. */
  33. int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
  34. /**
  35. * 表示转换成byte数组所需要的长度,
  36. * 其中shift的值1-二进制,3-八进制,4-十六进制。比
  37. * 如10的mag是4,如果要转成二进制shift=1,则chars=4,因为需要长度为4的字符数组来存放1010。
  38. * 如果要转成16进制a,则shift=4,得出chars=1,因为只需要长度为1的字符串数组来存放结果a.
  39. */
  40. int chars = Math.max(((mag + (shift - 1)) / shift), 1);
  41. if (COMPACT_STRINGS) {
  42. byte[] buf = new byte[chars];
  43. //将int值转化为对应进制的字符形式添加到buf数组中
  44. formatUnsignedInt(val, shift, buf, 0, chars);
  45. return new String(buf, LATIN1);
  46. } else {
  47. byte[] buf = new byte[chars * 2];
  48. formatUnsignedIntUTF16(val, shift, buf, 0, chars);
  49. return new String(buf, UTF16);
  50. }
  51. }
  52. /**
  53. 获取int值补码形式前面的0的个数,0返回32,负数返回0
  54. 该方法返回i的二进制从头开始有多少个0。i为0的话则有32个0。
  55. 这里处理其实是体现了二分查找思想的,先看高16位是否为0,是的话则至少有16个0,否则左移16位继续往下判断,
  56. 接着右移24位看是不是为0,是的话则至少有16+8=24个0,直到最后得到结果。
  57. */
  58. public static int numberOfLeadingZeros(int i) {
  59. if (i <= 0)
  60. return i == 0 ? 32 : 0;
  61. int n = 31;
  62. // 从最大数开始判断,依次将大数减小
  63. if (i >= 1 << 16) { n -= 16; i >>>= 16; }
  64. if (i >= 1 << 8) { n -= 8; i >>>= 8; }
  65. if (i >= 1 << 4) { n -= 4; i >>>= 4; }
  66. if (i >= 1 << 2) { n -= 2; i >>>= 2; }
  67. return n - (i >>> 1);// 返回二进制补码前面0的个数
  68. }
  69. //将int值转化为对应进制的字符形式添加到buf数组中
  70. static void formatUnsignedInt(int val, int shift, byte[] buf, int offset, int len) {
  71. /**
  72. * 二进制,因为2的1次方是2,所以shift就是1,那么radix就是1左移1位得到2,mask就是1,对应的二进制就是1;
  73. * 八进制,因为2的3次方是8,所以shift就是3,那么radix就是1左移3位得到8,mask就是7,对应的二进制就是111;
  74. * 十六进制,因为2的4次方是16,所以shift就是4,那么radix就是1左移4位得到16,mask就是15,对应的二进制就是1111;
  75. */
  76. int charPos = offset + len;
  77. int radix = 1 << shift;
  78. int mask = radix - 1; //掩码
  79. /**
  80. * 十进制数如果是转换成八进制或十六进制这种进制数为2的整数次方的进制,有更快的算法,就是先得到二进制,然后每几位一组转换。
  81. * 比如要把19转换成八进制:
  82. * 先把19转成二进制,也就是10011;
  83. * 因为8是2的3次方,所以把10011从低位开始每3位一组划分,也就是10 011;
  84. * 把10 011按每一组转为八进制,也就是2 3,所以19的八进制表示就是23。
  85. *
  86. * 循环val & mask 与运算的过程就像分组转换的过程,每次循环可以将mask对应的位数得到,再利用digits数组转换成对应的字符,这个字符就是这次分组的这几位所对应的结果,
  87. * 每次分组得到结果以后把val右移相应的位数,继续下一轮的循环分组。
  88. *
  89. * 比如val为19,shift为3,radix为8,mask为7。
  90. * 第一次循环:19 & 7 就是10011 & 111,结果为11,也就是3,通过digits数组得到这一位字符为3。然后10011右移3位,得到val为10。
  91. * 第二次循环:10 & 111,结果为10,也就是2,通过digits数组得到这一位字符为2。然后10右移3位,得到val为0,循环结束。
  92. * 最终结果就是23。
  93. */
  94. do {
  95. buf[--charPos] = (byte) Integer.digits[val & mask]; //分组转化算法思想
  96. val >>>= shift;
  97. } while (charPos > offset);
  98. }
  99. //使用两个byte存储字符形式添加
  100. private static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int offset, int len) {
  101. int charPos = offset + len;
  102. int radix = 1 << shift;
  103. int mask = radix - 1;
  104. do {
  105. StringUTF16.putChar(buf, --charPos, Integer.digits[val & mask]);
  106. val >>>= shift;
  107. } while (charPos > offset);
  108. }

4 parse系列方法

  1. //解析十进制的字符串形式数字并返回int值
  2. public static int parseInt(String s) throws NumberFormatException {
  3. return parseInt(s,10);
  4. }
  5. /**
  6. * 将对应进制的字符串形式转化为十进制int返回,
  7. * 比如: Integer.parseInt("10",16) = 16
  8. */
  9. public static int parseInt(String s, int radix)
  10. throws NumberFormatException
  11. {
  12. if (s == null) { throw new NumberFormatException("null"); }
  13. if (radix < Character.MIN_RADIX) { throw new NumberFormatException("radix " + radix +
  14. " less than Character.MIN_RADIX"); }
  15. if (radix > Character.MAX_RADIX) { throw new NumberFormatException("radix " + radix +
  16. " greater than Character.MAX_RADIX"); }
  17. boolean negative = false;//是否为负数
  18. int i = 0, len = s.length();
  19. int limit = -Integer.MAX_VALUE;// 最小值
  20. if (len > 0) {
  21. char firstChar = s.charAt(0);
  22. if (firstChar < '0') { // Possible leading "+" or "-"
  23. if (firstChar == '-') {
  24. negative = true;
  25. limit = Integer.MIN_VALUE;
  26. } else if (firstChar != '+') {
  27. throw NumberFormatException.forInputString(s);
  28. }
  29. if (len == 1) { // Cannot have lone "+" or "-"
  30. throw NumberFormatException.forInputString(s);
  31. }
  32. i++;
  33. }
  34. int multmin = limit / radix;
  35. int result = 0;
  36. while (i < len) {//循环计算每一位值
  37. //根据Character类获取当前对应字符对应进制的数字
  38. int digit = Character.digit(s.charAt(i++), radix);
  39. if (digit < 0 || result < multmin) {
  40. throw NumberFormatException.forInputString(s);
  41. }
  42. result *= radix; //乘进制数转换为十进制数结果
  43. if (result < limit + digit) {
  44. throw NumberFormatException.forInputString(s);
  45. }
  46. result -= digit;
  47. }
  48. return negative ? result : -result;
  49. } else {
  50. throw NumberFormatException.forInputString(s);
  51. }
  52. }
  53. /**
  54. * @since 1.8 将无符号的十进制字符串形式解析为int, 负数字符串形式会直接抛异常
  55. */
  56. public static int parseUnsignedInt(String s) throws NumberFormatException {
  57. return parseUnsignedInt(s, 10);
  58. }
  59. /**
  60. * @since 1.8 将对应进制的无符号字符串解析为int. 注意: "-10" 这种负数字符串形式会直接抛异常
  61. */
  62. public static int parseUnsignedInt(String s, int radix)
  63. throws NumberFormatException {
  64. if (s == null) {
  65. throw new NumberFormatException("null");
  66. }
  67. int len = s.length();
  68. if (len > 0) {
  69. char firstChar = s.charAt(0);
  70. if (firstChar == '-') {
  71. throw new
  72. NumberFormatException(String.format("Illegal leading minus sign " +
  73. "on unsigned string %s.", s));
  74. } else {
  75. if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
  76. (radix == 10 && len <= 9) ) { // Integer.MAX_VALUE in base 10 is 10 digits
  77. return parseInt(s, radix); //调用parseInt方法
  78. } else {
  79. long ell = Long.parseLong(s, radix);
  80. if ((ell & 0xffff_ffff_0000_0000L) == 0) {
  81. return (int) ell;
  82. } else {
  83. throw new
  84. NumberFormatException(String.format("String value %s exceeds " +
  85. "range of unsigned int.", s));
  86. }
  87. }
  88. }
  89. } else {
  90. throw NumberFormatException.forInputString(s);
  91. }
  92. }
  93. /**
  94. * 将对应进制的无符号CharSequence解析为int. 注意: "-10" 这种负数字符串形式会直接抛异常
  95. * 即可以使用StringBuffer等参数,逻辑与上面String参数是一样的
  96. * @since 9
  97. */
  98. public static int parseUnsignedInt(CharSequence s, int beginIndex, int endIndex, int radix)
  99. throws NumberFormatException {
  100. s = Objects.requireNonNull(s);
  101. if (beginIndex < 0 || beginIndex > endIndex || endIndex > s.length()) {
  102. throw new IndexOutOfBoundsException();
  103. }
  104. int start = beginIndex, len = endIndex - beginIndex;
  105. if (len > 0) {
  106. char firstChar = s.charAt(start);
  107. if (firstChar == '-') {
  108. throw new
  109. NumberFormatException(String.format("Illegal leading minus sign " +
  110. "on unsigned string %s.", s));
  111. } else {
  112. if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
  113. (radix == 10 && len <= 9)) { // Integer.MAX_VALUE in base 10 is 10 digits
  114. return parseInt(s, start, start + len, radix);
  115. } else {
  116. long ell = Long.parseLong(s, start, start + len, radix);
  117. if ((ell & 0xffff_ffff_0000_0000L) == 0) {
  118. return (int) ell;
  119. } else {
  120. throw new
  121. NumberFormatException(String.format("String value %s exceeds " +
  122. "range of unsigned int.", s));
  123. }
  124. }
  125. }
  126. } else {
  127. throw new NumberFormatException("");
  128. }
  129. }
  130. /**
  131. * 解析CharSequence为int,根据指定起始位置和进制数,即可以使用StringBuffer等参数,逻辑与上面String参数是一样的
  132. * @since 9
  133. */
  134. public static int parseInt(CharSequence s, int beginIndex, int endIndex, int radix)
  135. throws NumberFormatException {
  136. s = Objects.requireNonNull(s);
  137. if (beginIndex < 0 || beginIndex > endIndex || endIndex > s.length()) {
  138. throw new IndexOutOfBoundsException();
  139. }
  140. if (radix < Character.MIN_RADIX) {
  141. throw new NumberFormatException("radix " + radix +
  142. " less than Character.MIN_RADIX");
  143. }
  144. if (radix > Character.MAX_RADIX) {
  145. throw new NumberFormatException("radix " + radix +
  146. " greater than Character.MAX_RADIX");
  147. }
  148. boolean negative = false;
  149. int i = beginIndex;
  150. int limit = -Integer.MAX_VALUE;
  151. if (i < endIndex) {
  152. char firstChar = s.charAt(i);
  153. if (firstChar < '0') { // Possible leading "+" or "-"
  154. if (firstChar == '-') {
  155. negative = true;
  156. limit = java.lang.Integer.MIN_VALUE;
  157. } else if (firstChar != '+') {
  158. throw NumberFormatException.forCharSequence(s, beginIndex,
  159. endIndex, i);
  160. }
  161. i++;
  162. if (i == endIndex) { // Cannot have lone "+" or "-"
  163. throw NumberFormatException.forCharSequence(s, beginIndex,
  164. endIndex, i);
  165. }
  166. }
  167. int multmin = limit / radix;
  168. int result = 0;
  169. while (i < endIndex) {
  170. // Accumulating negatively avoids surprises near MAX_VALUE
  171. int digit = Character.digit(s.charAt(i), radix);
  172. if (digit < 0 || result < multmin) {
  173. throw NumberFormatException.forCharSequence(s, beginIndex,
  174. endIndex, i);
  175. }
  176. result *= radix;
  177. if (result < limit + digit) {
  178. throw NumberFormatException.forCharSequence(s, beginIndex,
  179. endIndex, i);
  180. }
  181. i++;
  182. result -= digit;
  183. }
  184. return negative ? result : -result;
  185. } else {
  186. throw NumberFormatException.forInputString("");
  187. }
  188. }

5 valueOf系列方法与静态内部缓存类

  1. /**
  2. * 静态内部类: 把-128~最大边界(默认是127)的数字缓存起来了,用于提升性能和节省内存
  3. * 最大边界可以通过-XX:AutoBoxCacheMax进行配置
  4. */
  5. private static class IntegerCache {
  6. static final int low = -128;
  7. static final int high;
  8. static final Integer cache[];//缓存数据
  9. static {
  10. // high value may be configured by property
  11. int h = 127;
  12. String integerCacheHighPropValue =
  13. VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
  14. if (integerCacheHighPropValue != null) {
  15. try {
  16. int i = parseInt(integerCacheHighPropValue);
  17. i = Math.max(i, 127);
  18. // Maximum array size is Integer.MAX_VALUE
  19. h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
  20. } catch( NumberFormatException nfe) {
  21. // If the property cannot be parsed into an int, ignore it.
  22. }
  23. }
  24. high = h;
  25. cache = new Integer[(high - low) + 1];
  26. int j = low;
  27. for(int k = 0; k < cache.length; k++)
  28. cache[k] = new Integer(j++);//往数组中提前加入创建好的对象
  29. // range [-128, 127] must be interned (JLS7 5.1.7)
  30. assert Integer.IntegerCache.high >= 127;
  31. }
  32. //构造器私有,保护数据
  33. private IntegerCache() {}
  34. }
  35. // 根据int返回Integer对象
  36. public static Integer valueOf(int i) {
  37. //如果在-128-high缓存区间内,则返回缓存里的对象,即区间内用valueOf返回的对象都是同一个,相等的
  38. if (i >= Integer.IntegerCache.low && i <= Integer.IntegerCache.high)
  39. return Integer.IntegerCache.cache[i + (-Integer.IntegerCache.low)];
  40. return new Integer(i);
  41. }
  42. // 根据字符串和进制基数构造Integer对象并返回
  43. public static Integer valueOf(String s, int radix) throws NumberFormatException {
  44. return Integer.valueOf(parseInt(s,radix));
  45. }
  46. // 根据String返回十进制Integer对象
  47. public static Integer valueOf(String s) throws NumberFormatException {
  48. return Integer.valueOf(parseInt(s, 10));
  49. }

7 getInteger和比较,hashCode等方法

  1. //Integer hash值是其value
  2. @Override
  3. public int hashCode() {
  4. return Integer.hashCode(value);
  5. }
  6. public static int hashCode(int value) {
  7. return value;
  8. }
  9. //比较value的int值是否相等,如果两个Integer的值应该用这个方法,而不是 ==
  10. public boolean equals(Object obj) {
  11. if (obj instanceof Integer) {
  12. return value == ((Integer)obj).intValue();
  13. }
  14. return false;
  15. }
  16. /**
  17. * Integer.getInteger(String)方法假设String参数是一个系统属性数值的名称,会读取该系统属性,
  18. * 然后把系统属性的值转换成一个数字。当我们调用Integer.getInteger("521") 应该是得到 null(系统默认肯定没有521的系统属性)。
  19. *
  20. * 常见的系统属性
  21. * 在JDK文档中System类中有这样的方法getProperties()在此方法的详细介绍中有下面的参数可供使用:
  22. * java.version  Java 运行时环境版本
  23. * java.vendor  Java 运行时环境供应商
  24. * java.vendor.url  Java 供应商的 URL
  25. * java.home  Java 安装目录
  26. * 当启动JVM时,请使用System.setProperty或使用-Dname = value标志
  27. */
  28. public static Integer getInteger(String nm) {
  29. return getInteger(nm, null);
  30. }
  31. public static Integer getInteger(String nm, int val) {
  32. Integer result = getInteger(nm, null);
  33. return (result == null) ? Integer.valueOf(val) : result;
  34. }
  35. public static Integer getInteger(String nm, Integer val) {
  36. String v = null;
  37. try {
  38. v = System.getProperty(nm);
  39. } catch (IllegalArgumentException | NullPointerException e) {
  40. }
  41. if (v != null) {
  42. try {
  43. return Integer.decode(v);
  44. } catch (NumberFormatException e) {
  45. }
  46. }
  47. return val;
  48. }
  49. /**
  50. * ecode合适用来分析数字
  51. * 可以分析
  52. * 8进:010=>分析后为 8
  53. * 10进:10=>分析后为 10
  54. * 16进:#10|0X10|0x10=>分析后是 16
  55. * 而valueof 只能分析纯数字的String
  56. * 像 010 这样的8进制 他会解析成 =>10
  57. */
  58. public static Integer decode(String nm) throws NumberFormatException {
  59. int radix = 10;
  60. int index = 0;
  61. boolean negative = false;
  62. Integer result;
  63. if (nm.length() == 0)
  64. throw new NumberFormatException("Zero length string");
  65. char firstChar = nm.charAt(0);
  66. // Handle sign, if present
  67. if (firstChar == '-') {
  68. negative = true;
  69. index++;
  70. } else if (firstChar == '+')
  71. index++;
  72. // Handle radix specifier, if present
  73. if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
  74. index += 2;
  75. radix = 16;
  76. }
  77. else if (nm.startsWith("#", index)) {
  78. index ++;
  79. radix = 16;
  80. }
  81. else if (nm.startsWith("0", index) && nm.length() > 1 + index) {
  82. index ++;
  83. radix = 8;
  84. }
  85. if (nm.startsWith("-", index) || nm.startsWith("+", index))
  86. throw new NumberFormatException("Sign character in wrong position");
  87. try {
  88. result = Integer.valueOf(nm.substring(index), radix);
  89. result = negative ? Integer.valueOf(-result.intValue()) : result;
  90. } catch (NumberFormatException e) {
  91. // If number is Integer.MIN_VALUE, we'll end up here. The next line
  92. // handles this case, and causes any genuine format error to be
  93. // rethrown.
  94. String constant = negative ? ("-" + nm.substring(index))
  95. : nm.substring(index);
  96. result = Integer.valueOf(constant, radix);
  97. }
  98. return result;
  99. }
  100. /**
  101. * 比较value值
  102. */
  103. public int compareTo(Integer anotherInteger) {
  104. return compare(this.value, anotherInteger.value);
  105. }
  106. //比较两个int大小
  107. public static int compare(int x, int y) {
  108. return (x < y) ? -1 : ((x == y) ? 0 : 1);
  109. }
  110. /**
  111. * 将两个数视为无符号比较,此时如果参数中不同号,结果会相反,同号的结果与compare()相同
  112. * ,任意一个参数如果有负数,加上MIN_VALUE,值会变成最大值
  113. */
  114. public static int compareUnsigned(int x, int y) {
  115. return compare(x + MIN_VALUE, y + MIN_VALUE);
  116. }

8 数学计算方法(重点,很多算法思想)

  1. /**
  2. * 返回i的二进制中最高位的1,其他全为0的值。
  3. * 比如i=10时,二进制即为1010,最高位的1,其他为0,则是1000
  4. * MIN_VALUE = 0x80000000 = 10000000000000000000000000000000 最高为1其他位为0 ,右移i的左边0的个数为得到i的最高位为1其他位为0的值,再 & 得到结果
  5. * >>>: 无符号右移,不管正负高位都补0
  6. */
  7. public static int highestOneBit(int i) {
  8. return i & (MIN_VALUE >>> numberOfLeadingZeros(i));
  9. }
  10. /**
  11. * 获取int值补码形式前面的0的个数,0返回32,负数返回0
  12. * 该方法返回i的二进制从头开始有多少个0。i为0的话则有32个0。
  13. * 这里处理其实是体现了二分查找思想的,先看高16位是否为0,是的话则至少有16个0,否则左移16位继续往下判断,
  14. * 接着右移24位看是不是为0,是的话则至少有16+8=24个0,直到最后得到结果。
  15. */
  16. public static int numberOfLeadingZeros(int i) {
  17. // HD, Count leading 0's
  18. if (i <= 0)
  19. return i == 0 ? 32 : 0;
  20. int n = 31;
  21. if (i >= 1 << 16) { n -= 16; i >>>= 16; }
  22. if (i >= 1 << 8) { n -= 8; i >>>= 8; }
  23. if (i >= 1 << 4) { n -= 4; i >>>= 4; }
  24. if (i >= 1 << 2) { n -= 2; i >>>= 2; }
  25. return n - (i >>> 1);
  26. }
  27. /**
  28. * 与highestOneBit方法对应,lowestOneBit获取最低位1,其他全为0的值。
  29. * 先取负数,得到的结果和i进行与操作,即 原码 & 补码 结果刚好是加的那个1
  30. */
  31. public static int lowestOneBit(int i) {
  32. return i & -i;
  33. }
  34. /**
  35. * 该方法主要用于计算二进制数中1的个数。
  36. * 先将重要的列出来,
  37. * 0x55555555等于01010101010101010101010101010101,
  38. * 0x33333333等于00110011001100110011001100110011,
  39. * 0x0f0f0f0f等于00001111000011110000111100001111。
  40. * 0x3f等于00000000000000000000000000111111
  41. * 核心思想就是先每两位一组统计看有多少个1,比如10011111则每两位有1、1、2、2个1,记为01011010,
  42. * 然后再算每四位一组看有多少个1,而01011010则每四位有2、4个1,记为00100100,
  43. * 接着每8位一组就为00000110,接着16位,32位,最终在与0x3f进行与运算,得到的数即为1的个数
  44. * 分治思想
  45. */
  46. public static int bitCount(int i) {
  47. i = i - ((i >>> 1) & 0x55555555);
  48. i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
  49. i = (i + (i >>> 4)) & 0x0f0f0f0f;
  50. i = i + (i >>> 8);
  51. i = i + (i >>> 16);
  52. return i & 0x3f;
  53. }
  54. /**
  55. * 该方法即是将i进行反转,反转就是第1位与第32位对调,第二位与第31位对调,以此类推。
  56. * 核心思想是先将相邻两位进行对换,比如10100111对换为0101 1011,接着再将相邻四位两两进行对换,对换后为1010 1101,
  57. * 接着将相邻八位四四进行对换,最后字节对换,即把32位中间的16位对换,然后最高8位再和最低8位对换。
  58. * 用到了典型的分治思想,先将每个字节(8位)自己全部反转,然后再将四个字节进行反转,可能开始看有点绕,下面逻辑详细分析一下:
  59. * 比如现在有一个32位: 标记前8位数字为 1 2 3 4 5 6 7 8
  60. * 第一次相邻对换后为: 2 1 4 3 6 5 8 7
  61. * 第二次相邻四个再两两对换: 4 3 2 1 8 7 6 5
  62. * 第三次相邻8个再四四对换: 8 7 6 5 4 3 2 1 刚好完成每个字节中的对换
  63. * 然后把32位四个字节进行对换得到结果,其中 1 刚好到了最后32位,以此类推
  64. */
  65. public static int reverse(int i) {
  66. i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
  67. i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
  68. i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
  69. return reverseBytes(i);
  70. }
  71. /**
  72. * 反转指定int值的字节数得到的值,即int 四个字节,第一个字节和最后一个字节调换位置,第二个和第三个调换位置
  73. * 核心思想: 将指定字节移动到指定位置,其他位置都置为0,然后|得出结果,
  74. */
  75. public static int reverseBytes(int i) {
  76. return (i << 24) | //左移24位,第四个字节移动到第一字节位置,后面全部补0
  77. ((i & 0xff00) << 8) | // 0xff00= 00000000 00000000 11111111 00000000 , 获取第三个字节并移动八位到第二个字节,其他位置全部为0
  78. ((i >>> 8) & 0xff00) | // 无符号右移8位,第二字节移动到第三字节位置并 & 运算获取第三字节,其他位为0
  79. (i >>> 24); // 无符号右移24位,第一字节移动到第四字节位置,其他位为0, 全部 | 运算即为反转后的值
  80. }
  81. /**
  82. * 循环移位: 就是把数值变成二进制,然后循环移动的过程;
  83. * 换句话说,循环移位就是将移出的低位放到该数的高位(循环右移)或把移出的高位放到该数的低位(循环左移)
  84. * 比如: -2 10000000000000000000000000000010 补码为: 111111111111111111111111111111110
  85. * 左移2位,即把最高的两位 11 -> 放到低位右边为 11111111111111111111111111111011 = -5
  86. * 核心思想就是把左移或者右移的几位数(左移后面补零,右移前面补零),再通过右移或者左移到最后面或者最前面几位,然后一与(都是0,原来是什么就会得到什么结果)
  87. * 比如 -2 前面的 11 通过 >>> -2 (右移30位,移到最后面,刚好是左移补的零,达到循环)
  88. * 11 111111111111111111111111111000
  89. * 000000000000000000000000000000 11 |
  90. * 11111111111111111111111111111011
  91. */
  92. public static int rotateLeft(int i, int distance) {//左移
  93. return (i << distance) | (i >>> -distance);
  94. }
  95. public static int rotateRight(int i, int distance) {//右移
  96. return (i >>> distance) | (i << -distance);
  97. }
  98. /**
  99. * 正数返回1,负数返回-1,0返回0
  100. */
  101. public static int signum(int i) {
  102. return (i >> 31) | (-i >>> 31);
  103. }
  104. //@since 1.8 无符号除法
  105. public static int divideUnsigned(int dividend, int divisor) {
  106. return (int)(toUnsignedLong(dividend) / toUnsignedLong(divisor));
  107. }
  108. //@since 1.8 无符号求余数
  109. public static int remainderUnsigned(int dividend, int divisor) {
  110. return (int)(toUnsignedLong(dividend) % toUnsignedLong(divisor));
  111. }
  112. public static int sum(int a, int b) { return a + b; }
  113. public static int max(int a, int b) { return Math.max(a, b); }
  114. public static int min(int a, int b) { return Math.min(a, b); }

三 总结

Integer对象相等问题

  1. @Test
  2. public void test01(){
  3. Integer a=127;
  4. Integer b=127;
  5. System.out.println(a==b);// true 自动装箱会使用缓存中同一个对象
  6. Integer d=new Integer(127);
  7. Integer e=new Integer(127);
  8. System.out.println(d==e); // false 使用new每次都是一个新对象
  9. Integer f=Integer.valueOf(127);
  10. Integer n=Integer.valueOf(127);
  11. System.out.println(f==n); // true valueOf方法会使用缓存中的对象 [-128,hign(默认127)] 之间都是同一个对象
  12. Integer c=129;
  13. System.out.println(a==c); // false 不同对象
  14. System.out.println(a==b.intValue()); //true Integer会拆箱转为int,进行比较数值
  15. System.out.println(a.equals(b)); //true 比较基本数值的值
  16. }

四 Long类源码分析

Long类源码逻辑跟Integer基本差不多,好多API都是一样的,可对照Integer阅读即可!,这里就不贴详细分析了!

JDK源码之Integer类分析的更多相关文章

  1. JDK源码之Byte类分析

    一 简介 byte,即字节,由8位的二进制组成.在Java中,byte类型的数据是8位带符号的二进制数,以二进制补码表示的整数 取值范围:默认值为0,最小值为-128(-2^7);最大值是127(2^ ...

  2. JDK源码之Boolean类分析

    一 简介 boolean类型的封装类,将基本类型为boolean的值包装在一个对象中,实现序列化接口,和Comparable接口 额外提供了许多便捷方法,比较简单,直接贴代码分析 二 源码分析 //t ...

  3. JDK源码之AbstractStringBuilder类分析

    一 概述 二 实现接口 AbstractStringBuilder实现了两个接口: Appendable 概述: Appendable的实现类的对象可以附加字符序列和值. 要追加的字符应该是Unico ...

  4. JDK源码之Double类&Float类分析

    一 概述 Double 类是基本类型double的包装类,fainl修饰,在对象中包装了一个基本类型double的值.Double继承了Number抽象类,具有了转化为基本double类型的功能. 此 ...

  5. JDK源码之String类解析

    一 概述 String由final修饰,是不可变类,即String对象也是不可变对象.这意味着当修改一个String对象的内容时,JVM不会改变原来的对象,而是生成一个新的String对象 主要考虑以 ...

  6. [Android FrameWork 6.0源码学习] LayoutInflater 类分析

    LayoutInflater是用来解析XML布局文件,然后生成对象的ViewTree的工具类.是这个工具类的存在,才能让我们写起Layout来那么省劲. 我们接下来进去刨析,看看里边的奥秘 //调用i ...

  7. jdk源码理解-String类

    String类的理解 简记录一下对于jdk的学习,做一下记录,会持续补充,不断学习,加油 1.String的hash值的计算方法. hash值的计算方法多种多样,jdk中String的计算方法如下,比 ...

  8. JDK源码阅读-Integer

    先上一版字符串转数值的几个方法的区别 parseInt(String s),解析字符串数,10进制,返回int parseInt(String s, int radix),解析字符串数,radix为指 ...

  9. jdk源码阅读-Object类

    native 关键字 private static native void registerNatives(); static { registerNatives(); } public final ...

随机推荐

  1. TCP/IP|| 建立连接或终止

    1.TCP是一个面向连接的协议,在双方发送数据时需要之间建立连接. 当使用telnet命令是连接对应的端口产生TCP连接,通过tcpdump命令查看TCP报文段的输出 源>目的:标志 在标识中有 ...

  2. 选题Scrum立会报告+燃尽图 03

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/8680 组长:杨天宇 组员:魏新,罗杨美慧,王歆瑶,徐丽君 组名:组长 第 ...

  3. $CH5501$ 环路运输 环形$+$单调队列

    CH Description 在一条环形公路旁均匀地分布着N座仓库,编号为1~N,编号为 i 的仓库与编号为 j 的仓库之间的距离定义为 dist(i,j)=min⁡(|i-j|,N-|i-j|),也 ...

  4. Spring中Bean的实例化与DI的过程

    引言 前文我们介绍了关于如何学习Spring的源码以及解析了spring中加载配置文件注册Beandefinition的过程.今天我们继续学习DI的过程. 创建实例和DI过程 IOC和DI都是对spr ...

  5. Java对象头与锁

    对象由多部分构成的,对象头,属性字段.补齐区域等.所谓补齐区域是指如果对象总大小不是4字节的整数倍,会填充上一段内存地址使之成为整数倍. 后面两个很好理解,今天我主要想总结一下对象头: 对象头这部分在 ...

  6. Linux 学习笔记 6 搭建nginx 实现二级域名访问

    前言 在前一节的内容里面,我们学习了如何使用yum 包管理工具来安装我们需要的软件,这节内容,通过搭建Nginx 反向代理服务器,以及学习服务的配置等内容. NGINX Nginx是一款轻量级的Web ...

  7. Spring学习记录3——Spring AOP

    SpringAOP基础 AOP简介: AOP是Aspect Oriented Programing的简称,翻译为“面向切面编程”.它适用于具有横切逻辑的应用场合,如性能检测,访问控制,事务管理及日志记 ...

  8. 关于django中的get_or_create方法的坑

    最近在项目中发现了这样的一个坑,那就是我们的需求是不能添加一个相同的对象到数据库中,就通过某些字段的值组合成唯一值到数据库中去查找数据,如果没有找到对象,那就创建一条新的数据库记录,而刚好django ...

  9. 主席树 - 查询某区间第 K 大

    You are working for Macrohard company in data structures department. After failing your previous tas ...

  10. Python解析json字符串,json字符串用法

    json数据简介 json数据是一个轻量级的数据交换格式,采用完全独立于语言的文本格式,这些特性使json称为理想的数据交换语言,易于人阅读和编写,同时易于机器解析和生成. json中的字符集必须是U ...