数据类型
1. 基本类型—官方介绍
基本数据类型 | 位数 | 数值范围 |
---|---|---|
short | 16 | -32768~32767 |
int | 32 | -2^31~2^31-1 |
long | 64 | -2^63~2^63-1 |
float | 32 | +-3.402823*10^38 |
double | 64 | +-1.79769313486231570*10^308 |
byte | 8 | -128~127 |
char | 16 | \u0000~\Uffff |
boolean | ~ | true,false |
boolean 只有两个值:true、false,可以使⽤ 1 bit 来存储,但是具体⼤⼩没有明确规定。JVM 会在编译时期将boolean 类型的数据转换为 int,使⽤ 1 来表示 true,0 表示 false。JVM ⽀持 boolean 数组,但是是通过读写byte 数组来实现的。
2. 包装类型
基本类型都有对应的包装类型,基本类型与其对应的包装类型之间的赋值使用自动装箱与拆箱完成。
Integer x = 2; // 装箱 调用了 Integer.valueOf(2)
int y = x; // 拆箱 调用了 X.intValue()
3. 缓存池
一个经典的问题:
public static void main(String[] args) {
Integer a = 127;
Integer b = 127;
System.out.printf("a==b: %s ", a == b);
Integer c = 128;
Integer d = 128;
System.out.printf("c==d: %s ", c == d);
Integer e = new Integer(127);
Integer f = new Integer(127);
System.out.printf("e==f:%s ", e == f);
}
输出为a==b: true c==d: false e==f:false
- 编译器会在自动装箱过程调用 valueOf() 方法,因此多个值相同且值在缓存池范围内的 Integer 实例使用自动装箱来创建,那么就会引用相同的对象。
- Integer缓存池大小为-128~127
new Integer(127) 与 Integer.valueOf(127) 的区别在于:
- new Integer(127) 每次都会新建一个对象;
- Integer.valueOf(127) 会使用缓存池中的对象,多次调用会取得同一个对象的引用。
所以a,b指向相同对象,c,d就是new了两个对象,e,f就是两个对象。
valueOf() 方法的实现比较简单,就是先判断值是否在缓存池中,如果在的话就直接返回缓存池的内容。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
编译器会在自动装箱过程调用 valueOf() 方法,因此多个值相同且值在缓存池范围内的 Integer 实例使用自动装箱来创建,那么就会引用相同的对象。
基本类型对应的缓冲池范围如下:
- boolean values true and false【true,false】
- all byte values【-128~127】
- short values between -128 and 127【-128~127】
- int values between -128 and 127【-128~127】
- long values between -128 and 127【-128~127】
- char in the range \u0000 to \u007F【0~127】
在使用这些基本类型对应的包装类型时,如果该数值范围在缓冲池范围内,就可以直接使用缓冲池中的对象。
在 jdk 1.8 所有的数值类缓冲池中,Integer 的缓冲池 IntegerCache 很特殊,这个缓冲池的下界是 - 128,上界默认是 127,但是这个上界是可调的,在启动 jvm 的时候,通过 -XX:AutoBoxCacheMax= 来指定这个缓冲池的大小,该选项在 JVM 初始化的时候会设定一个名为 java.lang.IntegerCache.high 系统属性,然后 IntegerCache 初始化的时候就会读取该系统属性来决定上界。