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

许多人可能认为在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.append("\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由于浮点型,存储方法的差异,并不存在此机制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值