对于java自动装箱与自动拆箱我目前只停留在知道使用的层面上,为了能够进一步的对其进行深入的研究,下面从源码开始对其进行分析。
分析类
最首先的当然是从类的继承实现情况开始。
public final class Integer extends Number implements Comparable<Integer> {...}
对与这个Integer类,它实现了Comparable接口,继承了Number.
Comparatable : 强行对实现它的类的每个实例进行自然排序,该接口的唯一方法compareTo方法被称为自然比较方法
Number类:继承了Serializable接口,内有实现对数操作的一些方法。
该类被final修饰,不可被继承
public关键字修饰,这个很好理解,这个类定义出来是被所有的类的使用的,包括Java的使用者定义的类来使用的。所以一定是public的。
分析属性
/** * The value of the {@code Integer}. * * @serial */ private final int value;
- Integer用于存储数据的属性,类型为整形
常量分析
//A constant holding the minimum value an int can have, -231. @Native public static final int MIN_VALUE = 0x80000000; //A constant holding the maximum value an int can have, 231-1. @Native public static final int MAX_VALUE = 0x7fffffff;
- 这两个属性都是一个整形变量,用来保存最大值与最小值
- 注解修饰成员变量,表示这个变量可以被本地代码引用
- final修饰 不可被修改
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
- 获取int类型的虚拟机类对象
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' };
- 数字为字符串类型的所有可能表现形式
方法分析
public static String toString(int i, int radix) { if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) radix = 10; /* 如果是10进制,直接转字符串即可 */ /* Use the faster version */ if (radix == 10) { return toString(i); } // 存放转换进制后的字符数组 char buf[] = new char[33]; boolean negative = (i < 0); // 将指针指向buf数组最后一位,以便后边存放字符 int charPos = 32; if (!negative) { i = -i; } /* 使用短除法来转换进制 */ while (i <= -radix) { buf[charPos--] = digits[-(i % radix)]; i = i / radix; } buf[charPos] = digits[-i]; if (negative) { buf[--charPos] = '-'; } return new String(buf, charPos, (33 - charPos)); }
- 返回由第二个参数指定的基数中的第一个参数的字符串表示形式,例如:Integer.toString(3,2),得到3的二进制表示形式。
public static String toUnsignedString(int i, int radix) { return Long.toUnsignedString(toUnsignedLong(i), radix); }
- 返回由第二个参数指定的基数中的第一个参数的字符串表示形式
public static String toString(int i) { if (i == Integer.MIN_VALUE) return "-2147483648"; int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); char[] buf = new char[size]; getChars(i, size, buf); return new String(buf, true); }
- 返回一个代表指定整形类型的String类型对象
public static String toUnsignedString(int i) { return Long.toString(toUnsignedLong(i)); }
将参数的字符串表示形式返回为无符号十进制值。
接下来,是这个封装类的最==重要==的几个方法:
public static int parseInt(String s, int radix) throws NumberFormatException { /* * WARNING: This method may be invoked early during VM initialization * before IntegerCache is initialized. Care must be taken to not use * the valueOf method. */ if (s == null) { throw new NumberFormatException("null"); } 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"); } int result = 0; boolean negative = false; int i = 0, len = s.length(); int limit = -Integer.MAX_VALUE; int multmin; int digit; 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); if (len == 1) // Cannot have lone "+" or "-" throw NumberFormatException.forInputString(s); i++; } multmin = limit / radix; while (i < len) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit(s.charAt(i++),radix); if (digit < 0) { throw NumberFormatException.forInputString(s); } 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; } 例子: parseInt("0", 10) returns 0 parseInt("473", 10) returns 473 parseInt("+42", 10) returns 42 parseInt("-0", 10) returns 0 parseInt("-FF", 16) returns -255 parseInt("1100110", 2) returns 102 parseInt("2147483647", 10) returns 2147483647 parseInt("-2147483648", 10) returns -2147483648 parseInt("2147483648", 10) throws a NumberFormatException parseInt("99", 8) throws a NumberFormatException parseInt("Kona", 10) throws a NumberFormatException parseInt("Kona", 27) returns 411787
- 将字符串参数解析为第二个参数指定的基数中的有符号整数。
public static int parseInt(String s) throws NumberFormatException { return parseInt(s,10); }
- 这个方法一看方法体就知道了,不用多说
public static int parseUnsignedInt(String s, int radix) throws NumberFormatException { if (s == null) { throw new NumberFormatException("null"); } int len = s.length(); 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 { if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits (radix == 10 && len <= 9) ) { // Integer.MAX_VALUE in base 10 is 10 digits return parseInt(s, radix); } else { long ell = Long.parseLong(s, radix); if ((ell & 0xffff_ffff_0000_0000L) == 0) { return (int) ell; } else { throw new NumberFormatException(String.format("String value %s exceeds " + "range of unsigned int.", s)); } } } } else { throw NumberFormatException.forInputString(s); } }
- 将字符串参数解析为第二个参数指定的基数中的无符号整数。
public static int parseUnsignedInt(String s) throws NumberFormatException { return parseUnsignedInt(s, 10); }
- 不多说,看方法体
public static Integer valueOf(String s, int radix) throws NumberFormatException { return Integer.valueOf(parseInt(s,radix)); }
- 返回一个
Integer
指定的int
值的Integer
实例。
public static Integer valueOf(String s) throws NumberFormatException { return Integer.valueOf(parseInt(s, 10)); }
- 看方法体
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
- 返回一个 Integer指定的 int值的 Integer实例
- 这个方法需要特别注意:IntegerCache为Integer类的缓存类,默认缓存了-128~127的Integer值,如遇到[-128,127]范围的值需要转换为Integer时会直接从IntegerCache中获取
/** * Constructs a newly allocated {@code Integer} object that * represents the specified {@code int} value. * * @param value the value to be represented by the * {@code Integer} object. */ public Integer(int value) { this.value = value;
- 构造方法
public Integer(String s) throws NumberFormatException { this.value = parseInt(s, 10); }
构造一个新分配的Integer对象,该对象表示由String参数表示的int值。字符串转换为int值的方式与parseInt方法用于基数10的方式完全相同。
public String toString() { return toString(value); }
- 重写Object类的toString()方法
@Override public int hashCode() { return Integer.hashCode(value); } public static int hashCode(int value) { return value; }
- 重写hashCode()方法
public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; }
- 重写equals()方法
/** * Compares two {@code Integer} objects numerically. * * @param anotherInteger the {@code Integer} to be compared. * @return the value {@code 0} if this {@code Integer} is * equal to the argument {@code Integer}; a value less than * {@code 0} if this {@code Integer} is numerically less * than the argument {@code Integer}; and a value greater * than {@code 0} if this {@code Integer} is numerically * greater than the argument {@code Integer} (signed * comparison). * @since 1.2 */ public int compareTo(Integer anotherInteger) { return compare(this.value, anotherInteger.value); } /** * Compares two {@code int} values numerically. * The value returned is identical to what would be returned by: * <pre> * Integer.valueOf(x).compareTo(Integer.valueOf(y)) * </pre> * * @param x the first {@code int} to compare * @param y the second {@code int} to compare * @return the value {@code 0} if {@code x == y}; * a value less than {@code 0} if {@code x < y}; and * a value greater than {@code 0} if {@code x > y} * @since 1.7 */ public static int compare(int x, int y) { return (x < y) ? -1 : ((x == y) ? 0 : 1); }
- 实现接口方法
/** * 返回指定int值的符号函数(所谓的符号函数就是确定输入值的符号【正数|负数|0】) * 如果指定值为负数,则返回值为-1;如果指定值为0,则返回值为0;如果指定值为正数,则返回值为1 * * @param i 要计算其符号的值 * @return 返回指定int值的符号,如果是负数返回-1,0返回0,正数返回1 */ public static int signum(int i) { // 如果是正数,则可以通过(-i >>> 31)确定符号,即获取最高位的符号。因为(i >> 31)会为0。 // 如果是负数,则可以通过(i >> 31)确定符号,即获取最高位的符号。因为(-i >>> 31)会为0。 return (i >> 31) | (-i >>> 31); }
- 返回指定int值的符号函数
- 分析:
/* (i >> 31) | (-i >>> 31) 第一种情况:i是正数,则返回1。例如i=96所对应的二进制是0000 0000 0000 0000 0000 0000 0110 0000 i=0000 0000 0000 0000 0000 0000 0110 0000 i>>31=0000 0000 0000 0000 0000 0000 0000 0000 -i=1111 1111 1111 1111 1111 1111 1010 0000 -i>>>31=0000 0000 0000 0000 0000 0000 0000 0001 (i >> 31) | (-i >>> 31) 0000 0000 0000 0000 0000 0000 0000 0000 | 0000 0000 0000 0000 0000 0000 0000 0001 =0000 0000 0000 0000 0000 0000 0000 0001 第二种情况:i是0,则返回0。 第三种情况:i是负数,则返回-1。例如i=-96所对应的二进制是1111 1111 1111 1111 1111 1111 1010 0000 i=1111 1111 1111 1111 1111 1111 1010 0000 i>>31=1111 1111 1111 1111 1111 1111 1111 1111 -i=0000 0000 0000 0000 0000 0000 0110 0000 -i>>>31=0000 0000 0000 0000 0000 0000 0000 0000 (i >> 31) | (-i >>> 31) 1111 1111 1111 1111 1111 1111 1111 1111 | 0000 0000 0000 0000 0000 0000 0000 0000 =1111 1111 1111 1111 1111 1111 1111 1111 */
public static int sum(int a, int b) { return a + b; }
- 返回两数之和
public static int max(int a, int b) { return Math.max(a, b); }
- 返回最大值
public static int min(int a, int b) { return Math.min(a, b); }
- 返回最小值
IntegerCache类
/** * Cache to support the object identity semantics of autoboxing for values between * -128 and 127 (inclusive) as required by JLS. * * The cache is initialized on first usage. The size of the cache * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option. * During VM initialization, java.lang.Integer.IntegerCache.high property * may be set and saved in the private system properties in the * sun.misc.VM class. */ private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 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]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {} }
面试:
/** * Integer的值在-128到127时(包括-128和127),Integer对象是在IntegerCache.cache产生,会复用已有对象, * 也就是说,这个区间的Integer可以直接用等号进行判断。 * Integer的值在-128到127之外时,Integer对象在堆上产生,不会复用已有对象,用等号会返回false。 * 建议老老实实用equals()方法来比较Integer对象。 * @param value */
案例1:
Integer a = 127; Integer b = 127; Integer c = 128; Integer d = 128; System.out.println(a==b); System.out.println(c==d); Integer e = -128; Integer f = -128; Integer g = -129; Integer h = -129; System.out.println(e==f); System.out.println(g==h);
输出:
true false true false
案例2:
public class EqualsMethod { public static void main(String[] args) { Integer n1 = new Integer(47); Integer n2 = new Integer(47); System.out.print(n1 == n2); System.out.print(","); System.out.println(n1 != n2); } } 选择以上程序段的输出结果为: A:false,false B:false,true C:true,false D:true,true
选择B,这里直接是new出来的对象不涉及缓存,n1,n2是不同的对象。
结论:
Integer的值在-128到127时,Integer对象是在IntegerCache.cache产生,会复用已有对象,也就是说,这个区间的Integer可以直接用等号进行判断。
Integer的值在-128到127之外时,Integer对象在堆上产生,不会复用已有对象,用等号会返回false