Java的8种数据类型
Java 的每个基本类型都对应了一个包装类型,比如说 int 的包装类型为 Integer
,double
的包装类型为 Double
。
基本类型 |
包装类 |
boolean |
Boolean |
byte |
Byte |
short |
Short |
int |
Integer |
long |
Long |
float |
Float |
double |
Double |
char |
Character |
为什么要有包装类
Java是一种面向对象的语言,而基本数据类型不属于对象,这给Java程序造成了一定的困难。因此,Java提供了封装类型,将基本数据类型包装成对象,并提供了自动拆装箱机制,使得基本数据类型可以作为对象被传递。
基本类型与包装类型的区别
二者初始值不同
包装类型可以为null
,而基本类型不可以。
它使得包装类型可以应用与POJO中,而基本类型不行。
POJO(Plain Ordinary Java Object)简单的Java对象,只有属性字段以及 setter
和 getter
方法,实际就是普通JavaBeans
,是为了避免和EJB混淆所创造的简称。
//POJO实例
class Writer {
private Integer age;
private String name;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
为什么 POJO 的属性必须要用包装类型?
数据库的查询结果可能是null
,如果使用基本类型的话,因为要自动拆箱(将包装类型转为基本类型,比如说把 Integer
对象转换成int
值),就会抛出 NullPointerException
的异常。
二者声明方式不同
包装类创建的是对象,而基本类型不是。
基本类型不使用new
关键字,而包装类型使用new
关键字分配存储空间。
二者存储区域不同
基本类型分配在栈内存,对象存储于堆内存。
int a=1;
Integer a =new Integer(1);
由于在堆内存分配空间所需时间远大于栈内存,基本类型分配空间所需时间更少,更高效。
二者存储内容不同
基本类型一般保存为数值;
而对象保存的是对象的地址。
二者使用方法不同
- 集合类中只能使用包装类,但基本类型可以自动装箱。
- 泛型中只能使用包装类,不可使用基本类型。
List<int> list = new ArrayList<>();
// 提示 Syntax error, insert "Dimensions" to complete ReferenceType
List<Integer> list = new ArrayList<>();
- 反射调用函数中使用包装类。
- 数据库查询结果为
null
时,无法赋值给基本类型,只能使用包装类。
自动拆装箱
自动拆装箱主要应对基本类型与包装类型的相互转换问题。
将基本类型转换成包装类型的过程叫做装箱。
反之,将包装类型转换成基本类型的过程叫做拆箱。
在 Java SE5
之前,开发人员要手动进行装拆箱
Integer chenmo = new Integer(10); // 手动装箱
int wanger = chenmo.intValue(); // 手动拆箱
Java SE5 为了减少开发人员的工作,提供了自动装箱与自动拆箱的功能。
Integer chenmo = 10; // 自动装箱
int wanger = chenmo; // 自动拆箱
//等价于
Integer chenmo = Integer.valueOf(10);
int wanger = chenmo.intValue();
也就是说,自动装箱是通过 Integer.valueOf()
完成的;
自动拆箱是通过 Integer.intValue()
完成的。
缓存池
当需要进行自动装箱时,如果数字在 -128 至 127 之间时,会直接使用缓存池中的对象,而不是重新创建一个对象。
// 1)基本类型和包装类型
int a = 100;
Integer b = 100;
System.out.println(a == b);//true
// 2)两个包装类型
Integer c = 100;
Integer d = 100;
System.out.println(c == d);//true
// 3)
Integer c = 200;
Integer d = 200;
System.out.println(c == d);//false
除了Float
和Double
之外,其他六个包装类都有常量缓存池 。
当然,这个问题只会发生在装箱时,也就是调用valueOf
方法时。
如果没有触发装箱操作时,不论值是否相等,新建对象的==比较都是false。
Integer a1 = 1;//调用Integer.valueOf()自动装箱
Integer b1 = 1;//调用Integer.valueOf()自动装箱
Integer c1 = 300;//调用Integer.valueOf()自动装箱
Integer d1 = 300;//调用Integer.valueOf()自动装箱
System.out.println(a1==b1);//true
System.out.println(c1==d1);//false
Integer a2 = Integer.valueOf(1);//手动装箱
Integer b2 = Integer.valueOf(1);//手动装箱
Integer c2 = Integer.valueOf(300);//手动装箱
Integer d2 = Integer.valueOf(300);//手动装箱
System.out.println(a2==b2);//true
System.out.println(c2==d2);//false
// 构造器传值,并没有调用valueOf方法,所以也没有缓冲池
Integer a3 = new Integer(1);//新建对象
Integer b3 = new Integer(1);//新建对象
Integer c3 = new Integer(300);//新建对象
Integer d3 = new Integer(300);//新建对象
System.out.println(a3==b3);//false
System.out.println(c3==d3);//false