JAVA 自动拆装箱详解

JAVA 自动拆装箱详解

1.自动拆装箱子的作用和意义

Java语言是一种面向对象的语言,但是Java中的基本数据类型不是面向对象的,不能之间参与面向对象的开发,为了解决这个不足,java 提供了8个基本类型对应的包装类,这样就可以参与面向对象的开发了
基本类型和装箱类型对照:

基本类型装箱类型
int (4字节)Integer
byte (1字节)Byte
double (8字节Double
short (2字节)Short
long (8字节)Long
char(2字节)Char
float (4字节)Float
boolean (未定)Boolean

2.什么是自动拆装箱

1) 装箱、拆箱:把基本类型转化为对应的包装类,叫做装箱,反之,把包装类转换成基本类型叫做拆箱
其中,6个数字类型的包装类继承自java.lang.Number,Number是一个抽象类,定义了可以让数字类型之间 进行互转的方法。
例如:

	int a = 5;
	Integer a1 = Integer.valueOf(a);//装箱,把int 变量转化为 Integer 对象
	int b = a1.intValue();//拆箱,把 Integer 对象a1 转化为 基本类型 b

2)数字类型的包装类都有两个常量:MAX_VALUE,MIN_VALUE,用于表示其对应的基本类型数据的取值范围
例如:

int max = Integer.MAX_VALUE;
int min = Integer.MIN_VALUE;
long lmax = Long.MAX_VALUE;

3)包装类支持一个静态方法:parseXXX(String str),可以将给定的字符串解析为对应的基本类型,但是前提是该字符串内容必须正确表示基本类型可以保存的值。
例如:

String str = "123";
		int d = Integer.parseInt(str);
		double dou = Double.parseDouble(str);

自动拆箱,装箱:DK1.5之后推出了一个特性:自动拆装箱。该特性是编译器认可,而非JVM认可。编译器在编译源代码时会自动补全基本类型与包装类之间的转换代码完成相互转换工作,从而让我们在编写源代码时实现了基本类型与包装类之间相互赋值的操作
例如:

/*
		 * 触发了编译器自动拆箱特性
		 * 编译器会自动补全代码完成包装类转换为
		 * 基本类型的操作,下面代码在class文件
		 * 中会被改为:
		 * int d = new Integer(1).intValue();
		 */
		int d = new Integer(1);
		/*
		 * 触发了编译器自动装箱特性
		 * 编译器会自动补全代码完成基本类型转换为
		 * 包装类的操作,下面代码在class文件
		 * 中会被改为:
		 * Integer in = Integer.valueOf(1);
		 */
		Integer in = 1;

3.自动拆装箱使用的注意事项

例如:

 		Integer a = 1;
        Integer b = 1;
        Integer c = 144;
        Integer d = 144;
        Integer a1 = new Integer(1);
        Integer b1 = new Integer(1);
        System.out.println(a == b);         //true
        System.out.println(a.equals(b));    //true
        System.out.println(a1 == b1);       //false
        System.out.println(a1.equals(b1));  //true
        System.out.println(c == d);         //false
        System.out.println(c.equals(d));    //true

第7行为true而第12行为false呢?这是因为:
JVM会自动维护八种基本类型的常量池,int常量池中初始化的范围是 -128~127,所以当为Integer i=127时,在自动装箱过程中是取自常量池中的数值,而当Integer i=128时已经超过了int的范围,128不在常量池范围内,所以在自动装箱过程中需new 128,所以地址不一样

4.源码剖析

看一下Integer类的源码。首先看valueOf()方法:

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
}
其中 ,IntegerCache.low和 IntegerCache.high的值参考下面代码
  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() {}
    }

由此看见,在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,基本类型的常量池中被重用。所以在调用valueOf()方法的时候,会判断你所给的数是不是在IntegerCache.low 和 i <= IntegerCache.high之间,如果是,则从常量池中取数据,而不在这个范围里的数,你每次所生成的对象都是不同的。
自动装箱池的大小是怎么定义的呢,Integer.java中有这样一个内部类
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) {
try {
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);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
IntegerCache类,定义了Integer自动装箱池的大小。从源码中我们可以看到,下界是写死的(-128),但是上界却是由参数integerCacheHighPropValue 解析的,说明我们可以通过改变integerCacheHighPropValue值的大小来自定义自动装箱池的上限大小。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

*勇往直前*

带你装逼带你飞

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值