对象包装器
将基本数据类型包装在对象中,通过定义属性和方法来丰富数据类型的操作,这样的类称作对象包装器类.java中的对象包装器类有 Byte,Short,Integer,Long,Float,Double,Boolean,Character,Void.
特点:
- 对象包装器类是不可变的,因为它包装的基本类型值是final修饰的
- 对象包装器类是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;
}
}