1.包装类与基本类型
八种基本数据类型并不支持面向对象编程,基本类型的数据不具备“对象”的特性——不携带属性、没有方法可调用。这种非面向对象技术的做法会带来一定不便,如引用类型数据均继承了 Object 类的特性,要转换为 String 类型(经常有这种需要)时只要简单调用 Object 类中定义的toString()即可,而基本数据类型转换为 String 类型则要麻烦得多。为解决此类问题 ,Java为每种基本数据类型分别设计了对应的类,称之为包装类,也有教材称为外覆类或数据类型类。
基本类型 | 大小 | 包装器类型 |
---|---|---|
boolean | / | Boolean |
char | 16bit | Character |
byte | 8bit | Byte |
short | 16bit | Short |
int | 32bit | Integer |
long | 64bit | Long |
float | 32bit | Float |
double | 64bit | Double |
void | / | Void |
其中,如int、long等都是基本类型,直接存数值。
如:int i = 5;//直接在栈中分配空间,存放5这个数值
Integer是int的包装类,那么作为类就拥有方法;
如:
Integer i = new Integer(5);
//i是对象的引用变量,所以在堆内存中分配对象空间,栈中存放堆内存中对应空间的地址
1、Integer 是 int 的包装类,int 则是 java 的一种基本数据类型
2、Integer 变量必须实例化后才能使用,而int变量不需要
3、Integer 实际是对象的引用,当new一个 Integer时,实际上是生成一个指针指向此对象;而 int 则是直接存储数据值
4、Integer的默认值是null,int的默认值是0
2.装箱和拆箱
装箱:将基本类型用它们对应的引用类型包装起来。如将int包装成Integer类的对象。
拆箱:将包装类型转换为基本数据类型。将Integer类的对象重新简化成int基本类型。
Java 在1.5之后提供了自动的装箱和拆箱机制。基本数据类型可以和与其对应的包装类之间自动进行转换。
可以通过 Integer 类的构造方法将 int 装箱或者valueOf,通过 Integer 类的 intValue 方法将 Integer 拆箱。
int i = 10;
Integer j = new Integer(i); //手动装箱
Integer k = i; //自动装箱 相当于Integer k = Integer.valueOf(i)
int l = j.intValue(); //手动拆箱
int m = k; //自动拆箱
除此之外
- 将字符串转为整数。Integer 类有一个静态的 paseInt() 方法,可以将字符串转换为整数
parseInt(String s, int radix);
int i = Integer.parseInt("10000", 10);
其中,s为要转换的字符串,radix 为进制,可选,默认为十进制。
- 将整数转换为字符串。Integer 类有一个静态的 toString() 方法,可以将整数转换为字符串。
String s = Integer.toString(100);
3.Integer、new Integer() 和 int 的比较
- 1、两个 new Integer() 变量比较,永远是 false,因为new生成的是两个对象,其内存地址不同。
Integer i = new Integer(100);
Integer j = new Integer(100);
System.out.print(i == j); //false
- 2、Integer变量 和 new Integer() 变量比较 ,永远为 false。因为 Integer变量 指向的是 java 常量池 中的对象,而 new Integer() 的变量指向 堆中 新建的对象,两者在内存中的地址不同。
Integer i = new Integer(100);
Integer j = 100;
System.out.print(i == j); //false
- 3、两个Integer 变量比较,如果两个变量的值在区间-128到127 之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为 false 。
原因:
public static Integer valueOf(int i){
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high){
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}
java对于-128到127之间的数,会进行缓存。所以在通过valueOf方法创建Integer对象的时候,如果数值在 [-128,127] 之间,便返回指向IntegerCache.cache(常量池)中已经存在的引用;否则创建一个新的Integer对象。
那么当Integer i = 127 时,会将127进行缓存,下次再写Integer j = 127时,就会直接从缓存中取,就不会new了。
Integer i = 100;
Integer j = 100;
System.out.print(i == j); //true,此处i和j指向同一对象
Integer i = 128;
Integer j = 128;
System.out.print(i == j); //false,指向不同的对象
- 4、 int 变量 与 Integer、 new Integer() 比较时,只要两个的值是相等,则为true。因为包装类Integer 和 基本数据类型int 比较时,java会自动拆包装为int ,然后进行比较,实际上就变为两个int变量的比较。
int i = 128;
Integer i2 = 128;
Integer i3 = new Integer(128);
System.out.println(i == i2); // Integer会自动拆箱为int,所以为true
System.out.println(i == i3); // true,理由同上
注意
- Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的,因为他们都实现了常量池技术,Double、Float的valueOf方法的实现是类似的,并没有实现常量池技术。
Double i1 = 100.0;
Double i2 = 100.0;
Double i3 = 200.0;
Double i4 = 200.0;
System.out.println(i1==i2); //false
System.out.println(i3==i4); //false
因为在某个范围内的整型数值的个数是有限的,而浮点数却不是。所以Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现。
- 引入常量池的原因是速度更快,常量池引入的目的是为了避免频繁的创建和销毁对象而影响系统性能,其实现了对象的共享。这是一种享元模式的实现。