0%

Java基本数据类型

前言

本文介绍Java的基本数据类型与其对应的包装类型,以及装箱与拆箱。

Java包含8个基本数据类型,基本类型都有对应的包装类型,基本类型与其对应的包装类型之间的赋值使用自动装箱与拆箱完成。

Java基本数据类型与包装类

基本类型 大小 包装类
boolean / Boolean
byte 1个字节 Byte
char 2个字节 Character
short 2个字节 Short
int 4个字节 Integer
long 8个字节 Long
float 4个字节 Float
double 8个字节 Double

boolean类型:JVM在编译时将boolean类型的数据转换为int,1表示true,0表示false;若是boolean数组,通过byte数组来实现的。

为什么Java有包装类:

因为Java的基本数据类型不是对象,无法向上转型使用Object提供的方法。
例如,需要将String类型转换为int类型,由于String是一个对象而不是类型,若没有包装类Integer则无法转型;集合中只存储对象(引用类型),而不存储基本类型;多线程中的同步操作的也是对象。

装箱与拆箱

装箱: 自动将基本数据类型转换为包装类型。

拆箱: 自动将包装类型转换为基本数据类型。

1
2
Integer i = 10; //装箱, 自动调用Integer的valueOf(10)方法
int x = i; //拆箱, 自动调用Integer的intValue方法,int x = i.intValue

缓存池

由于基本数据类型在自动装箱过程中会使用缓存机制提高效率,在缓存范围类相同值的自动装箱对象相同。

基本类型对应的缓存池范围:

基本类型 大小 包装类 缓存范围 说明
boolean / Boolean true, false 全部缓存
byte 1个字节 Byte -128~127 全部缓存
char 2个字节 Character 0~127 部分缓存
short 2个字节 Short -128~127 部分缓存
int 4个字节 Integer -128~127 部分缓存,上界可以通过JVM启动参数 -XX:AutoBoxCacheMax= 来指定这个缓冲池的大小
long 8个字节 Long -128~127 部分缓存
float 4个字节 Float / 没有缓存
double 8个字节 Double / 没有缓存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args){
Integer a = new Integer(123);//每次都会创建一个新的对象, 不会触发自动装箱
Integer b = new Integer(123);//每次都会创建一个新的对象, 不会触发自动装箱
System.out.println(a == b); //false
Integer c = Integer.valueOf(123); //等价于Integer c = 123;
Integer d = Integer.valueOf(123); //等价于Integer d = 123;
System.out.println(c == d);//true
Integer e = 123; //装箱, 调用valueOf(123)
Integer f = 123; //装箱, 调用valueOf(123)
System.out.println(e == f);//true
Integer g = 200; //装箱,调用valueOf(200), 200超过了缓存池的大小, 会new Integer(200);
Integer h = 200; //装箱,调用valueOf(200), 200超过了缓存池的大小, 会new Integer(200);
System.out.println(g == h);//false
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main(String[] args){
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Long h = 2L;
Double i1 = 1.2;
Double i2 = 1.2;

System.out.println(c==(a+b)); //true, a + b会触发自动拆箱, 调用intValue(), 因为+这个操作符不适用于Integer对象, c==3, Integer对象无法与数值进行直接比较, 所以c自动拆箱转为int值3, 因此3 == 3
System.out.println(c.equals(a+b));//true, equals会触发自动装箱
System.out.println(g==(a+b));//true, 值相同,且在缓存范围内
System.out.println(g.equals(a+b));//false, equals触发装箱时, 如果数值是int型, 则调用Integer.valueOf();如果数值是long型, 则调用Long.valueOf()
System.out.println(g.equals(a+h));//true
System.out.println(i1 == i2);//false, Float,Double 并没有实现常量池技术
}

==与equals():

基本类型 == equals
非字符串变量 对象在内存中的首地址 对象在内存中的首地址
字符串变量 对象在内存中的首地址 字符串内容
基本类型 不可用
包装类 地址 内容