自动装箱和自动拆箱,对象包装类型的缓存机制

对象包装器

将基本数据类型包装在对象中,通过定义属性和方法来丰富数据类型的操作,这样的类称作对象包装器类.java中的对象包装器类有 Byte,Short,Integer,Long,Float,Double,Boolean,Character,Void.

特点:

  1. 对象包装器类是不可变的,因为它包装的基本类型值是final修饰的
  2. 对象包装器类是final修饰的,所以不能扩展它

java自动拆箱和自动装箱是jdk1.5之后引进的,是一种编译现象,编译器在生成字节码的时候,会插入必要的方法调用.

自动装箱:当一个int类型的值赋值给Interget变量时,int类型会被包装成一个Integer类型的对象

自动拆箱:当一个Integer类型的对象赋值给int时,Integer类的对象会自动的拆箱变为一个int值;

自动装箱和拆箱在算术表达式中比较频繁,如下

 

通过反编译工具可以看出

自动装箱时调用的是 public static Integer valueOf(int i)方法

自动拆箱时调用的是 public static intValue()方法

对象包装器类的相关类图

Number源码分析

抽象类Number是BigDecimal,BigInteger,Byte,Double,Float,Integer,Long和Short类的超类.Number的子类必须提供将表示的数值转换为byte,double,float,int,long和short的方法

public abstract class Number implements Serializable{
	private static final long serialVersionUID = -8742448824652078965L; 
	
	
	/**
	 * 以byte形式返回指定的数值,涉及到舍入或取整
	 * @return 转换为byte类型后该对象表示的值
	 */
	public byte byteValue() {
		return (byte)intValue();
	}
	
	/**
	 * 以short形式返回指定的数值,涉及到舍入或取整
	 * @return 转换为short类型后该对象表示的值
	 */
	public short shortValue(){
		return (short)intValue();
	}
	
	/**
	 * 以int形式返回指定的数值,涉及到舍入或取整
	 * @return 转换为int类型后该对象表示的值
	 */
	public abstract int intValue();

	/**
	 * 以long形式返回指定的数值,涉及到舍入或取整
	 * @return 转换为long类型后该对象表示的值
	 */
	public abstract long longValue();
	
	/**
	 * 以double形式返回指定的数值,涉及到舍入
	 * @return 转换为long类型后该对象表示的值
	 */
	public abstract double doubleValue();
	
	
	/**
	 * 以float形式返回指定的数值,涉及到舍入
	 * @return 转换为float类型后该对象表示的值
	 */
	public abstract float floatValue();
	
}

 

 

Comparable接口

此接口强行对实现它的每个类的对象进行整体排序,这种排序被称为类的自然排序
类的compareTo方法被称为它的自然比较方法
实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,实现此接口的对象可以用作
有序映射中的键或有序集合中的元素,无需指定比较器


public interface Comparable<T>{
	public int compareTo(T o);
}

Serializable接口(是个标记接口)

类通过实现java.io.Serializable接口来启用其序列化功能,未实现此接口对的类将无法使其任何状态序列化或反序列化.
可序列化的所有子类型本身都是可序列化的.
要允许不可序列化类的子类型序列化,可以假定该子类型负责保存和恢复超类型的public,protected和(如果可访问)包字
段的状态的责任.子类型可以承担此责任,只有当它扩展的类具有可访问的无参构造器来初始化类的状态时,才可以假定
子类型有此职责,如果不是这种情况,则声明一个类可序列化类时错误的
 如果可序列化类未显示声明serialVersionID,则序列化运行时将基于该类的各个方面计算该类的默认serialVersionUID值

public interface Serializable {
}

 Integer,Short,Byte,Character,Long的缓存

 Integer,Short,Byte,Character,Long等使用静态内部类提供了缓存机制用于将常用的数据[-128,127]对象存储.提高内存的利用率和效率,因此当自动装箱时,相同的int值对应的包装对象指向同一个引用,只有当int值不在缓存中时,才会创建新的对象.其中Integer的包装类型可以通过修改JVM参数来指定缓存的上限.

public class Integer extends Number{
    private final int value;

    private static class IntegerCache{
        static final low = -128;        //缓存的默认下限
        static final high;              //缓存的默认上限
        static final Integer[] cache;   //保存缓存的Integer对象

        static{
            int h = 127;        //设置默认的缓存上限
            
            // 获取jvm关于java.lang.Integer.IntegerCache.high的设置
            String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); 

            if(integerCacheHighPropValue != null){
                try{
                    // 将integerCacheHighPropValue解析为int,如果不能解析,则抛出 NumberFormatException 异常,默认不对这个异常做处理
                    int i = parseInt(integerCacheHighPropValue);
                    /* 查看设置值是否大于默认值,如果设置值未大于默认值,则继续使用默认上限127,即设置IntegerCache.high的值无效,此时缓存数组
                       的大小为 127 - (IntegerCahe.low)+1=256(加1是因为1~127,-1~127中没有包括0)
                    */ 
                    i = Math.max(i,127);
                    /**
                        查看此时的上限值是否大于Integer.MAX_VALUE-(-low)-1(
                            为什么是这个值呢?
                                因为数组的大小最大只能取到MAX_VALUE,默认缓存下限是low=-128,所以要减去
                                -128~-1和0所占的数组空间.
                        )
                        如果大于,则设置缓存的上限为Integer.MAX_VALUE,即设置参数不起作用
                     */
                    h = Math.min(i,Integer.MAX_VALUE-(-low)-1);     
                }catch(NumberFormatException nfe){

                }
            }

            high = h;       //获得最终的缓存上限
            // 创建缓存数组并循环赋值
            cache = new Integer[high-low+1];
            int j = low;
            for(int k = 0;k<cache.length;k++){
                cache[k] = new Integer(j++);
            }
            assert Integer.high >= 127;
        }
    }

    public static Integer valueOf(int i){
        if(i >= IntegerCache.low && i<= IntegerCache.high)
            return IntegerCache.cache[i+(-IntegerCache.low)];
        return new Integer(i);
    }

    public static intValue(){
        return value;
    }
  
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值