八种基本类型:byte short int long float double char boolean 都有对应的包装类
数据类型 | 包装类 | 字节长度 | 默认值 | 有效位 |
byte | Byte | 1 | 0 | -128~127 |
short | Short | 2 | 0 | -32768~32767 |
int | Intrger | 4 | 0 | -2^31-1~2^31 |
long | Long | 8 | 0l | -2^63~2^63-1 |
float | Float | 4 | 0.0f | 24(二进制)=7~8(十进制) |
double | Double | 8 | 0.0 | 53(二进制)=10~11(十进制) |
char | Character | 2 | u0000 | |
boolean | Boolean | 1 | false |
八种基本类型和其对应的封装类可以相互转换
通过故构造器手动转换转换,将基本类型转为包装类:
public void testWrapper()
{
int i = 10;
Integer integer = new Integer(i);
//每个基本类型的封装类都有自己的构造器,传入构造参数完成封装
//装箱操作
System.out.println(integer);
float f = 1.3f;
Float f1 = new Float(f);
System.out.println(f1);
char a = 'A';
Character character = new Character(a);
}
值得注意:在JDK1.5 JDK提供了自动装箱和自动拆箱功能
基本类型可以直接转换为包装类
public void testWrapper1() {
Integer i = new Integer(1);
int i1 = i;
System.out.println(i1);
i.equals(i1);
}
有了自动拆箱和自动装箱,基本类型与包装类的转换也更加方方便。
这里再引出一个问题:就是Integer的构造器Integer.valueOf();
这个函数有一个特殊的地方(源码的实现)
现有实例:
public void method() {
Integer i = new Integer(1);
Integer j = new Integer(2);
System.out.println(i == j);// false
Integer m =1;
Integer n = 1;
System.out.println(m ==n);//true
Integer x = 128;
Integer y = 128;
System.out.println(x == y);// false
}
为什么会出现上述的结果?
在Integer的构造器中,有一个Byte类型的数组,主要储存-128~127的数字。
因此,在创建-128~127范围的整形时,直接将该数组中该值对应的地址付给整形对象。但是当创建的数字不在该范围时,
构造器就需要分配地址,来储存新的值。
在Integer的构造函数中,它分两种情况:
1、i >= 128 || i < -128 =====> new Integer(i)
2、i < 128 && i >= -128 =====> SMALL_VALUES[i + 128]
那么上面的的结果就很好理解:
- 首先,现在为包装类,包装类中的==是比较地址,很明显,第一个1和2的地址是不同的 所以为false。
- 第二个,因为两个1都取自相同的地址(数组中值为1对应的地址)于是结果为true
- 第三个,由于128超过了数组的范围,因此。每当定义该变量时就需要重新分配空间,于是乎,虽然两个包装类的整形值都为128,但是,由于地址不同 因此,结果为false
拓展:八种基本类型中,有一部分的构造对象中是有类似于整形包装类的数组
这里再加入别人关于拆装箱的总结:
- 需要知道什么时候会引发装箱和拆箱
- 装箱操作会创建对象,频繁的装箱操作会消耗许多内存,影响性能,所以可以避免装箱的时候应该尽量避免。
- equals(Object o) 因为原equals方法中的参数类型是封装类型,所传入的参数类型(a)是原始数据类型,所以会自动对其装箱,反之,会对其进行拆箱
- 当两种不同类型用==比较时,包装器类的需要拆箱, 当同种类型用==比较时,会自动拆箱或者装箱