Integer源码解析

来源:互联网 发布:鹰眼监控软件注册机 编辑:程序博客网 时间:2024/06/07 16:03


这篇博客我来整理下以Integer为例整理下包装类的源码。首先来看一段代码:

public class LinkinPark{public static void main(String[] args){Integer a = 1;Integer b = 1;// 下行代码输出trueSystem.out.println(a == b);Integer c = 128;Integer d = 128;// 下行代码输出falseSystem.out.println(c == d);}}

上面的结果输出估计大家都很明白,前面的包装类那篇博客中我也已经整理到了,Integer类中使用了享元模式,然后用了一个缓存,用来缓存-128到127的数字

现在我们来从头到尾研究下Integer类的源码。

1),Integer类继承Number类,关于Number类我后面会专门整理,实现了comparable接口

public final class Integer extends Number implements Comparable<Integer>{/** * 最小值:-2147483648 */@Nativepublic static final int MIN_VALUE = 0x80000000;/** * 最大值:2147483647 * 不好记住肿么办?2开头的10位数字 */@Nativepublic static final int MAX_VALUE = 0x7fffffff;/** * 包装类中的基本类型的值 */private final int value;public Integer(int value){this.value = value;}public Integer(String s) throws NumberFormatException{this.value = parseInt(s, 10);}/** * 使用第二个参数指定的基数,将字符串参数解析为有符号的整数。 *  * @param s 包含要解析的整数表示形式的 String * @param radix 解析 s 时使用的基数,一般为10,用来转换数字 * @return 使用指定基数的字符串参数表示的整数 * @throws NumberFormatException */public static int parseInt(String s, int radix) throws NumberFormatException{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_VALUEdigit = 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;}// 以下提供几个转换值的方法public byte byteValue(){return (byte) value;}public short shortValue(){return (short) value;}public int intValue(){return value;}public long longValue(){return (long) value;}public float floatValue(){return (float) value;}public double doubleValue(){return (double) value;}@Overridepublic int hashCode(){return Integer.hashCode(value);}public boolean equals(Object obj){if (obj instanceof Integer){return value == ((Integer) obj).intValue();}return false;}public static int compare(int x, int y){return (x < y) ? -1 : ((x == y) ? 0 : 1);}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);}}
以上代码比较简单,我就不多做赘述啦。这里重点来看下Integer类使用的缓存,源码如下:

public final class Integer extends Number implements Comparable<Integer>{/** * 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 propertyint 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_VALUEh = 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(){}}public static Integer valueOf(int i){if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}}
分析一下上面的代码,在Integer的内部封装一个私有的静态内部类,然后在内部类中定义一个静态cache数组,初始化数组将一定范围的整数放到cache数组中,然后在调valueOf

方法的时候首先判断范围然后从缓存数组中去抓取数据,源码还是比较简单的。


缓存是一种非常优秀的设计模式,在Java,JavaEE平台的很多地方都会通过缓存来提高系统的运行性能。简单的说,如果你需要一台电脑,那么你就去买了一台电脑,但你不可

能一直使用这台电脑,你总会离开这台电脑。在你离开电脑的这段时间内,你如何做?你会不会立即把电脑扔掉?当然不会,你会把电脑放在房间,等下次又需要电脑时直接开机

使用,而不是再去购买一台。假设电脑是内存中的对象,而你的房间是内存,如果房间足够大,则可以把所有的曾经用过的各种东西都缓存起来,但这不可能,房间的空间是有限

制的,因此有些东西你用过一次就扔掉了,你只会把一些购买成本大,需要频繁使用的东西保存下来,类似的,Java也会把一些创建成本大,需要频繁使用的对象缓存起来,从而

提高程序的运行性能


前面贴出的代码中缓存那块其实也可以不使用静态内部类,直接使用一个静态数组就OK的,如下代码我自己模拟了一个LinkinInteger,实现了同样的功能。

public final class LinkinInteger{private final int value;public LinkinInteger(int value){this.value = value;}private static final int low = -128;private static final int high = 127;private static final LinkinInteger[] cache = new LinkinInteger[-(low) + high + 1];static{for (int i = 0; i < cache.length; i++){cache[i] = new LinkinInteger(i + low);}}public static LinkinInteger valueOf(int i){if (i >= low && i <= high){return cache[i + (-low)];}return new LinkinInteger(i);}public static void main(String[] args){// 下面3行代码没有使用缓存,所以输出falseLinkinInteger a = new LinkinInteger(1);LinkinInteger b = new LinkinInteger(1);System.out.println(a == b);// 下面3行代码使用了缓存,所以输出trueLinkinInteger c = LinkinInteger.valueOf(1);LinkinInteger d = LinkinInteger.valueOf(1);System.out.println(c == d);}}


1 0
原创粉丝点击