您的位置:首页 > 编程语言 > Java开发

Integer源码解析

2016-05-22 16:55 531 查看
这篇博客我来整理下以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);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息