简介
Java为每个基本数据类型设计了一个相对应的类,用于封装基本数据类型的值,这些类称为包装类。
包装类的作用:Java是一门面向对象的语言,但并不是一门存粹的面向对象的语言,Java中基本数据类型的变量就没有对象的特征,在某些情况下,这会很不方便,为了让基本数据类型的变量也具有对象的特征,就出现了包转类,它会把一个基本数据类型的变量封装到一个实例中。
有哪些包装类:Integer、Byte、Short、Long、Float、Double、Character、Boolean。其中,Integer、Byte、Short、Long、Float、Double都有一个共同的父类,Number,因为它们都是数字
使用案例
案例1:int和Integer之间的转换
// 创建一个Integer类型的包装类,它封装了一个int类型的数据
Integer i = Integer.valueOf(10);
// 提取出包装类中封装的数据
int i1 = i.intValue();
System.out.println("i1 = " + i1);
其它包装类的操作基本类似
安全地将string转换为int
使用Integer.parseInt,如果转换失败,它会报错,或者在转换之前判断字符串的格式是否是数字
案例:
@Test(expected = Exception.class)
public void testStringToInt() {
String s = Long.MAX_VALUE + "";
// 转换
int i;
try {
i = Integer.parseInt(s);
} catch (NumberFormatException e) {
throw new RuntimeException(e);
}
}
安全地将long转换为int
先判断范围,然后转换,如果超出范围就报错,及时提醒,避免潜在的bug。
@Test
public void testLongToInt() throws Exception {
Long maxValue = Long.valueOf(Long.MAX_VALUE);
// 下面这几行封装成一个方法会更加合适
if (maxValue > Integer.MAX_VALUE || maxValue < Integer.MIN_VALUE) {
throw new RuntimeException("long类型的值超出范围,不支持转换为int,long = " + maxValue);
}
int value = maxValue.intValue();
System.out.println(value);
}
装箱和拆箱
装箱:将基本数据类型封装到包装类对象中,Interger i = Integer.valueOf(1);
拆箱:将包转类中包转的基本数据类型取出,int i = integer.intValue();
自动拆箱和自动装箱:jdk1.5之后提供自动拆装箱功能,它是一种语法糖,
- 自动装箱:
Integer i = 1;
在编译的时候,会编译为:Integer i = Integer.valueOf(1);
- 自动拆箱:
int i2 = i
,i是Integer类型,在编译时会被编译为int i2 = i.intValue();
包装类编码规约
所有的相同类型的包装类对象之间值的比较,全部使用equals()方法。
所有实体类的静态变量必须使用包装类数据类型
所有的局部变量使用基本数据类型
包装类内部的缓存
以Integer为例,它会为-128到127之间的所有数字,分别创建Integer实例,然后缓存起来
public static Integer valueOf(int i) {
// 如果数字在指定范围内,从缓存中获取
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
// 存储缓存的实例
static final Integer cache[];
使用包装类来查看整数和小数在内存中的存储
整数在内存中的存储
整数在内存中是使用补码进行存储的,Integer类中的toBinaryString可以打印出任意整数的补码
toBinaryString:public static String toBinaryString(int i)
:返回任意一个数的二进制形式,是该数的补码
案例:
System.out.println("Integer.toBinaryString(5) = "
+ Integer.toBinaryString(5)); //101,不足32位,因为省略掉了前面的0
System.out.println("Integer.toBinaryString(-5) = "
+ Integer.toBinaryString(-5)); // 11111111111111111111111111111011
代码解析:
- 5的原码:0000 0101 // 以字节类型的数据做解析,方便理解,转换为int类型的数据,在前面补0或1即可,取决于byte类型的数据的第一位是0还是1
- -5的原码:1000 0101
- -5的反码:1111 1010
- -5的补码:1111 1011
浮点数在内存中的存储
使用Float类的floatToRawIntBits方法,可以打印出浮点数的十进制形式,然后再将十进制的数转成二进制。
floatToRawIntBits:public static native int floatToRawIntBits(float value)
:返回浮点数的十进制形式
代码案例:
System.out.println("Float.floatToRawIntBits(2.5f) = "
+ Integer.toBinaryString(FloatfloatToRawIntBits(2.5f)));
// 01000000001000000000000000000000 // 如果结果不足32位,在前面补0
System.out.println("Float.floatToRawIntBits(-2.5f) = "
+ Integer.toBinaryString(FloatfloatToRawIntBits(-2.5f)));
// 11000000001000000000000000000000
System.out.println("Float.floatToRawIntBits(0.5f) = "
+ Integer.toBinaryString(FloatfloatToRawIntBits(0.5f)));
// 00111111000000000000000000000000
System.out.println("Float.floatToRawIntBits(-0.5f) = "
+ Integer.toBinaryString(Float.floatToRawIntBits(-0.5f)));
// 10111111000000000000000000000000
代码解析:
∵ 2.5的二进制形式是10.1,可以转换为1.01 * 10^1
∴ 浮点数 2.5的符号位是0,表示正数,指数位是1,尾数位是01,在打印结果中:0 10000000 01000000000000000000000,符号位是0,因为指数位采取移位存储的方式,偏移量是127,01111111,所以指数位的存储是:10000000,尾数位01直接放到尾数中
∵ 0.5 的二进制形式是 0.1,可以转换为 1.0 * 10^(-1)
∴ 浮点数 0.5的符号位是0,表示正数,指数位是-1,尾数位是0,在打印结果中:0 01111110 00000000000000000000000,符号位是0,因为指数位采取移位存储的方式,偏移量是127,01111111,
所以指数位的存储是:01111110,尾数位0直接放到尾数中
2.5和-2.5,除了符号位不一样,其它全一样