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的版本信息:
首先看以下在java环境中的测试代码:
结果如下
之所以结果中Integer.valueOf(mint11j) == Integer.valueOf(mint11j)相等与Integer.valueOf(mint129) == Integer.valueOf(mint129))不等,是因为有一个内部机制
也就是通过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中测试代码,我们可以进行比较
以上表明,Integer 对象可以直接赋值,也可以Integer 与 int比较,这点需要注意下。我们看下结果
我们发现无论是java还是android只要是通过new 方法建立的对象,无法直接用==判断是否相等,因为他们是指向了堆区(heap),他们的对象指向了不同的地址,所以无法相等,同时android中直接赋值11为啥相等,而129不等呢,这是由于android做了一个优化。具体代码如下:
Integer会初始化256个常量,范围从 -128到127,然后作为一个Cache,从而减少非必要重复调用。这个范围外将会各种new了,也是上面的结论了。
那其他类型呢,例如Double,Float、Short等~
Double与Float没有对应的优化,而Byte与Long有类似的代码
Long型中
Byte型号
Short中
但是有两个奇怪的对象,分别是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);
结论:
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由于浮点型,存储方法的差异,并不存在此机制。
以下是各个sdk对应jdk的版本信息:
平台版本 | SDK版本 | JDK版本 |
2.2 | 8 | 5 |
2.3.3 | 10 | 6 |
4.0.3 | 15 | 6 |
4.1 | 16 | 6 |
4.2.x | 17 | 6 |
4.3 | 18 | 6 |
4.4 | 19 | 6 |
5 | 21 | 7 |
5.1 | 22 | 7 |
6.0 | 23 | 7 |
//为了方法查看,命名规则为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由于浮点型,存储方法的差异,并不存在此机制。
相关文章推荐
- Integer类型自动缓存-128到127的256个数字
- 为什么Java byte 类型的取值范围是-128~127 (转)
- Java基础知识强化65:基本类型包装类之Integer的构造方法
- 为什么Java byte 类型的取值范围是-128~127
- 为什么Java byte 类型的取值范围是-128~127
- Android中的java基础(二)——装箱与拆箱及不同基本类型的比较(类型转换)
- java中的byte类型的取值范围是-128~127
- 为什么Java byte 类型的取值范围是-128~127
- Java基础回顾--基本数据类型包装类1【Integer与int解惑】
- 为什么JavaByte类型的取值范围是-128~127
- 一道面试题关于Integer的缓存范围(-128~127)所引起的一系列问题记录
- 为什么java中Byte类型的取值范围是-128~127
- 为什么Java byte 类型的取值范围是-128~127
- Java基础知识强化67:基本类型包装类之Integer直接赋值的面试题
- 为什么Java byte 类型的取值范围是-128~127
- 为什么Java byte 类型的取值范围是-128~127
- 为什么Java byte 类型的取值范围是-128~127
- 为什么Java byte 类型的取值范围是-128~127
- Java基础知识强化69:基本类型包装类之Character案例(统计字符串中大写小写以及数字的次数)
- 关于Java中Byte类型的取值范围是-128~127的理解