您的位置:首页 > 移动开发 > Android开发

Android中的java基础(一)——Integer等数字基本类型的-128到127范围的缓存

2017-01-10 21:40 393 查看
许多人可能认为在Android中使用的java函数以及方法对象等相关东西就完全就是jdk的内容,然而并不是,Android使用的是android.jar中java包内的东西,不是直接使用jdk中的东西。而且Android对应jdk版本,随着Android的sdk版本不同而不同。

以下是各个sdk对应jdk的版本信息:

平台版本SDK版本 JDK版本
2.28 5
2.3.3 106
4.0.3156
4.1166
4.2.x176
4.3186
4.4196
5217
5.1227
6.0237
首先看以下在java环境中的测试代码:

//为了方法查看,命名规则为m+New(是否new)+Type(类型名称)+值+识别字符(a,b,c...)
Integer mNewInteger11A = new Integer(11);
Integer mNewInteger11B = new Integer(11);
Integer mNewInteger129G = new Integer(129);
int mint11j = 11;
int mint129 = 129;
System.out.println("(mNewInteger11A == mNewInteger11B)" + (mNewInteger11A == mNewInteger11B));
System.out.println("(mNewInteger11A.equals(mNewInteger11B))" + (mNewInteger11A.equals(mNewInteger11B)));
System.out.println("(Integer.valueOf(mint11j) == Integer.valueOf(mint11j))" + (Integer.valueOf(mint11j) == Integer.valueOf(mint11j)));
System.out.println("(Integer.valueOf(mint129) == Integer.valueOf(mint129)))" + (Integer.valueOf(mint129) == Integer.valueOf(mint129)));


结果如下

(mNewInteger11A == mNewInteger11B)false //作为两个不同的对象处理,指向堆区地址不同
(mNewInteger11A.equals(mNewInteger11B))true //进行值比较
(Integer.valueOf(mint11j) == Integer.valueOf(mint11j))true //JAVA中Integer有默认的缓存机制,两个指向同一个地址
(Integer.valueOf(mint129) == Integer.valueOf(mint129)))false


之所以结果中Integer.valueOf(mint11j) == Integer.valueOf(mint11j)相等与Integer.valueOf(mint129) == Integer.valueOf(mint129))不等,是因为有一个内部机制
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

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) {
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);
}
high = h;

cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}

private IntegerCache() {}
}


也就是通过Valueof进行比较的时候,注意下范围为 -128到127。(这个和Android的范围相同的!Android-128到127)

而在JAVA工程中,如果JDK小于1.5,则Integer对象不能直接通过 = 等号赋值,同时在java环境中 Integer 不能直接与 int比较,否则会报错



而JDK大于等于1.5以上的时候,由于Jdk加入的装箱、拆箱的操作,从而可以通过=等号直接赋值,同时也可以直接对比,同时Android继承了JDK对应的属性,Android工程中Integer对象也可以通过 = 等号赋值,也可以Integer 与 int直接比较,但是Integer对象与其他对象是不能比较的,但是可以和基本类型(int,double,float等)比较,实质上这里进行了拆箱操作,通过intValue方法等转化成int等基本类型,讲解见下一篇文章。

以下是Android中测试代码,我们可以进行比较

//为了方法查看,命名规则为m+New(是否new)+Type(类型名称)+值+识别字符(a,b,c...)
Integer mNewInteger11A = new Integer(11);
Integer mNewInteger11B = new Integer(11);
Integer mInteger11C = 11;
Integer mInteger11D = 11;
Integer mInteger129E = 129;
Integer mInteger129F = 129;
Integer mNewInteger129G = new Integer(129);
int mint129i = 129;
int mint11j = 11;
StringBuffer mStrBuffer = new StringBuffer();
mStrBuffer.append("\n");
mStrBuffer.append("\n(mNewInteger11A == mNewInteger11B)" + (mNewInteger11A == mNewInteger11B));
mStrBuffer.ap
4000
pend("\n(mNewInteger11A.equals(mNewInteger11B))" + (mNewInteger11A.equals(mNewInteger11B)));
mStrBuffer.append("\n(mNewInteger11A== mInteger11C)" + (mNewInteger11A== mInteger11C));
mStrBuffer.append("\n(mInteger11D== mInteger11C)" + (mInteger11D== mInteger11C));
mStrBuffer.append("\n(mInteger129E== mInteger129F)" + (mInteger129E== mInteger129F));
mStrBuffer.append("\n(mInteger129E == mNewInteger129G)" + (mInteger129E == mNewInteger129G));
mStrBuffer.append("\n(mInteger129E.equals(mNewInteger129G))" + (mInteger129E.equals(mNewInteger129G)));
mStrBuffer.append("\n(mInteger129E== Integer.valueOf(mint129i)))" + (mInteger129E== Integer.valueOf(mint129i)));
mStrBuffer.append("\n(Integer.valueOf(mint129i) == Integer.valueOf(mint129i))" + (Integer.valueOf(mint129i) == Integer.valueOf(mint129i)));
mStrBuffer.append("\n(mInteger11D== Integer.valueOf(mint11j))" + (mInteger11D== Integer.valueOf(mint11j)));
mStrBuffer.append("\n(Integer.valueOf(mint11j) == Integer.valueOf(mint11j))" + (Integer.valueOf(mint11j) == Integer.valueOf(mint11j)));


以上表明,Integer 对象可以直接赋值,也可以Integer 与 int比较,这点需要注意下。我们看下结果

(mNewInteger11A == mNewInteger11B)false //new的对象指向不同的堆的地址
(mNewInteger11A.equals(mNewInteger11B))true //值比较相同
(mNewInteger11A== mInteger11C)false //一个指向系统初始化的缓冲期是11的对象,另一个指向对球新建的11地址
(mInteger11D== mInteger11C)true //都指向系统初始化的缓存器是11的对象,因为Integer会初始化-128到127的数字,通过赋值初始化的过程会进入valueof的过程(详情见下解释)
(mInteger129E== mInteger129F)false //因为129不在系统缓存里,那么129分别通过valueof初始化2次
(mInteger129E == mNewInteger129G)false //第一个是通过valueof函数new的,
(mInteger129E.equals(mNewInteger129G))true //值比较相同
((mInteger129E== Integer.valueOf(mint129i)))false //因为大于127,通过valueOf函数new的
(Integer.valueOf(mint129i) == Integer.valueOf(mint129i))false //因为大于127,通过valueOf函数new的
(mInteger11D== Integer.valueOf(mint11j))true //因为大于-129小于等于127,通过valueOf函数取的缓存的
(Integer.valueOf(mint11j) == Integer.valueOf(mint11j))true //因为两个都大于-129小于等于127,通过valueOf函数取的缓存的


我们发现无论是java还是android只要是通过new 方法建立的对象,无法直接用==判断是否相等,因为他们是指向了堆区(heap),他们的对象指向了不同的地址,所以无法相等,同时android中直接赋值11为啥相等,而129不等呢,这是由于android做了一个优化。具体代码如下:

/**
* Returns a {@code Integer} instance for the specified integer value.
* <p>
* If it is not necessary to get a new {@code Integer} instance, it is
* recommended to use this method instead of the constructor, since it
* maintains a cache of instances which may result in better performance.
*
* @param i
*            the integer value to store in the instance.
* @return a {@code Integer} instance containing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
return  i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128];
}

/**
* A cache of instances used by {@link Integer#valueOf(int)} and auto-boxing
*/
private static final Integer[] SMALL_VALUES = new Integer[256];

static {
for (int i = -128; i < 128; i++) {
SMALL_VALUES[i + 128] = new Integer(i);
}
}


Integer会初始化256个常量,范围从 -128到127,然后作为一个Cache,从而减少非必要重复调用。这个范围外将会各种new了,也是上面的结论了。

那其他类型呢,例如Double,Float、Short等~

Double与Float没有对应的优化,而Byte与Long有类似的代码

Long型中

public static Long valueOf(long v) {
return  v >= 128 || v < -128 ? new Long(v) : SMALL_VALUES[((int) v) + 128];
}

/**
* A cache of instances used by {@link Long#valueOf(long)} and auto-boxing.
*/
private static final Long[] SMALL_VALUES = new Long[256];

static {
for (int i = -128; i < 128; i++) {
SMALL_VALUES[i + 128] = new Long(i);
}
}


Byte型号

public static Byte valueOf(byte b) {
return VALUES[b + 128];
}

/**
* A cache of instances used by {@link Byte#valueOf(byte)} and auto-boxing
*/
private static final Byte[] VALUES = new Byte[256];

static {
for (int i = -128; i < 128; i++) {
VALUES[i + 128] = new Byte((byte) i);
}
}


Short中

public static Short valueOf(short s) {
return s < -128 || s >= 128 ? new Short(s) : SMALL_VALUES[s + 128];
}

/**
* A cache of instances used by {@link Short#valueOf(short)} and auto-boxing.
*/
private static final Short[] SMALL_VALUES = new Short[256];

static {
for (int i = -128; i < 128; i++) {
SMALL_VALUES[i + 128] = new Short((short) i);
}
}


但是有两个奇怪的对象,分别是Character与Boolean

Character中

public static Character valueOf(char c) {
return c < 128 ? SMALL_VALUES[c] : new Character(c);
}

/**
* A cache of instances used by {@link #valueOf(char)} and auto-boxing
*/
private static final Character[] SMALL_VALUES = new Character[128];

static {
for (int i = 0; i < 128; i++) {
SMALL_VALUES[i] = new Character((char) i);
}
}

他的有效范围是0到127
Boolean中

/**
* The {@code Boolean} object that represents the primitive value
* {@code true}.
*/
public static final Boolean TRUE = new Boolean(true);

/**
* The {@code Boolean} object that represents the primitive value
* {@code false}.
*/
public static final Boolean FALSE = new Boolean(false);
public static Boolean valueOf(String string) {
return parseBoolean(string) ? Boolean.TRUE : Boolean.FALSE;
}
Boolean 的valueOf函数初始化2个值,通过valueof或者=等号赋值的自动装箱,比较的是这两个静态对象。

结论:

1.android与java基本类型用法相同,但是来自不同的包。

2.android数字基本对象类型可以直接赋值,例如Integer i = 1;JDK版本1.5以下的java不可,否则直接报错,1.5及以上的JDK版本和android处理方式相同。

3.jdk版本1.5及以上的环境中可以Integer与int直接进行比较,比较中,Integer通过intValue函数拆包比较,Integer也可和其他double、float等基本类型直接比较,而java不可,否则直接报错。

4.android及java jdk1.5版本以上环境中中Integer在-128到127范围内直接赋值数字和valueOf函数得到的值比较,通过==
相同,不在-128到127范围的其他值不同,同时注意在-128到127范围内均为Integer对象,只是随系统初始化这256个对象作为一个Cache缓冲区。其他类型只有Long、Byte、Short有同样范围及类似机制,Boolean范围就两个值,而Character范围为0到127,而Float以及Double由于浮点型,存储方法的差异,并不存在此机制。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息