Integer源码阅读

对于java自动装箱与自动拆箱我目前只停留在知道使用的层面上,为了能够进一步的对其进行深入的研究,下面从源码开始对其进行分析。

分析类

最首先的当然是从类的继承实现情况开始。

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

对与这个Integer类,它实现了Comparable接口,继承了Number.

  1. Comparatable : 强行对实现它的类的每个实例进行自然排序,该接口的唯一方法compareTo方法被称为自然比较方法
  2. Number类:继承了Serializable接口,内有实现对数操作的一些方法。
  3. 该类被final修饰,不可被继承
  4. 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;
  1. 这两个属性都是一个整形变量,用来保存最大值与最小值
  2. 注解修饰成员变量,表示这个变量可以被本地代码引用
  3. 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:falsefalse
B:falsetrue
C:truefalse
D:truetrue

选择B,这里直接是new出来的对象不涉及缓存,n1,n2是不同的对象。

结论:

  1. Integer的值在-128到127时,Integer对象是在IntegerCache.cache产生,会复用已有对象,也就是说,这个区间的Integer可以直接用等号进行判断。
  2. Integer的值在-128到127之外时,Integer对象在堆上产生,不会复用已有对象,用等号会返回false
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值