java包装类的自动封装、自动拆箱和缓存
/**
* 包装类的自动封装、自动拆箱和缓存
*/
public class TestWrapper2 {
public static void main(String[] args) {
Integer i1 = 1;
//自动封装 通过编译器编译后转变为 Integer i1 = Integer.valueOf(1); 供虚拟机执行
//Integer i1 引用类型变量
int i2 = i1;
//自动拆箱 通过编译器编译后转变为 int i2 = i1.intValue(); 供虚拟机执行
//int i2 基本数据类型
Integer i3 = null;
i2 = i3;
//运行时报错NullPointerException 在虚拟机运行时代码已经变为 i2 = i3.intValue() 但i3为null空指针 没有指向对象就找不到.intValue()方法
Integer i4 = 4000;
Integer i5 = 4000;
System.out.println(i4==i5);
//结果false i4 = Integer.valueOf(4000) Integer静态方法.valueOf()执行后会new一个新的对象给i4 value值为4000
//i5 = Integer.valueOf(4000) 同样会new一个新的对象给i5 i4和i5分别指向两个对象
System.out.println(i4.equals(i5));
//结果true Integer重写的equals()方法 在判断i5 instanceof Integer 判断i5是Integer的实例后比较i4和i5的value 两个value都是4000所以true
Integer i6 = 123;
Integer i7 = 123;
System.out.println(i6==i7);
//结果true 原因:在Integer初始化时缓存了整数范围在[-128,127]之间的包装类对象
//当i6 = Integer.valueOf(123)时 方法没有new新的包装类对象 而是将缓存中提前创建好的value=123的对象返回给i6
//i7 = 123同理 i6和i7指向的是同一个对象
/*
public static Integer valueOf(int i) {
//静态方法valueOf() 返回Integer类对象
if (i >= IntegerCache.low && i <= IntegerCache.high)
//IntegerCache整数缓存 .low=-128 .high=127 系统运行时已经提前建好了-128到127的整数的包装类放到了缓存数组中
return IntegerCache.cache[i + (-IntegerCache.low)];
//当判断i在-128到127之间 返回对应的对象
return new Integer(i);
//当i不在缓存数组的范围内是new对象返回
*/
}
}
class ImitateInteger {
//imitate模仿Integer缓存数组
private int value;
//每个对象对应一个value值
private ImitateInteger(int i){
//将构造器私有 外部生成对象时需要通过.valueOf()方法
this.value = i;
}
private static final int LOW = -128;
//模拟[-128,127] 两个值设为final常量 private仅方法内判断时调用 static这个属性不需要给对象
private static final int HIGH = 127;
private static final ImitateInteger[] cache = new ImitateInteger[HIGH-LOW+1];
//创建一个数组准备缓存[-128,127]之间的对象 -128到-1是128个 1到127是127个 再加一个0 [127-(-128)+1]
//换一种想法 从HIGH到LOW总共有HIGH-LOW个数 包含HIGH没包含LOW 所以再+1
static {
//静态初始化块 在类加载时执行
for (int i=LOW;i<=HIGH;i++){
cache[i+(-LOW)] = new ImitateInteger(i);
//数组的index范围[0]-[255] i=LOW i-LOW=0 i=HIGH i-LOW=255
//将value=-128的对象交给cache[0] value=127的对象交给cache[255]
//在类加载时即缓存new了-128到127
}
}
public static ImitateInteger valueOf(int i){
//public供外部调用的代替私有构造器的方法 代替构造器所以返回ImitateInteger对象
if (i>=LOW&&i<=HIGH){
//判断i是否在[-128,127]区间
return cache[i+(-LOW)];
//对应静态初始化快中的缓存数组 i对应的对象的index要加128即(-LOW)
}
return new ImitateInteger(i);
//不在区间内则new新对象返回
}
public static void main(String[] args) {
ImitateInteger i1 = ImitateInteger.valueOf(1);
ImitateInteger i2 = ImitateInteger.valueOf(1);
System.out.println(i1==i2);
//结果true i1和i2都没有new对象 返回了cache[1+(-(-128))]即cache[129] cache[129].value对应1
ImitateInteger i3 = ImitateInteger.valueOf(200);
ImitateInteger i4 = ImitateInteger.valueOf(200);
System.out.println(i3==i4);
//结果false i3和i4分别指向new新生成的对象
}
public boolean equals(Object o){
//重写继承自Object 的equals()
if (o instanceof ImitateInteger){
return this.value==((ImitateInteger)o).value;
//比较两个对象的value 将o强转为ImitateInteger
}
return false;
//不是同类返回false
// this.equals(o); 用来比较两个对象所以不是static方法
}
public int intValue(){
return this.value;
//int a = i4.intValue(); 将包装类转为基本数据类型 要转换的是对象 所以不用static
}
@Override
public String toString() {
//重写toString
return ""+this.value;
//返回值只能是字符串
}
}