Integer源码解析
Posted LinkinPark8林肯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Integer源码解析相关的知识,希望对你有一定的参考价值。
这篇博客我来整理下以Integer为例整理下包装类的源码。首先来看一段代码:
public class LinkinPark
public static void main(String[] args)
Integer a = 1;
Integer b = 1;
// 下行代码输出true
System.out.println(a == b);
Integer c = 128;
Integer d = 128;
// 下行代码输出false
System.out.println(c == d);
上面的结果输出估计大家都很明白,前面的包装类那篇博客中我也已经整理到了, Integer类中使用了享元模式,然后用了一个缓存,用来缓存-128到127的数字。
现在我们来从头到尾研究下Integer类的源码。
1),Integer类继承Number类,关于Number类我后面会专门整理,实现了comparable接口。
public final class Integer extends Number implements Comparable<Integer>
/**
* 最小值:-2147483648
*/
@Native
public static final int MIN_VALUE = 0x80000000;
/**
* 最大值:2147483647
* 不好记住肿么办?2开头的10位数字
*/
@Native
public 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_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;
// 以下提供几个转换值的方法
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;
@Override
public 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 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()
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行代码没有使用缓存,所以输出false
LinkinInteger a = new LinkinInteger(1);
LinkinInteger b = new LinkinInteger(1);
System.out.println(a == b);
// 下面3行代码使用了缓存,所以输出true
LinkinInteger c = LinkinInteger.valueOf(1);
LinkinInteger d = LinkinInteger.valueOf(1);
System.out.println(c == d);
以上是关于Integer源码解析的主要内容,如果未能解决你的问题,请参考以下文章