Java中的8个基本类型
数据类型 | boolean | byte | char | short | int | long | float | double |
---|---|---|---|---|---|---|---|---|
包装类型 | Boolean | Byte | Character | Short | Integer | Long | Float | Double |
bit | 32 | 8 | 16 | 16 | 32 | 64 | 64 | 64 |
基本类型的两条准则:
- 对整型数据不指定类型默认为int类型,浮点数默认为double类型
- 基本数据类型从小(字节)到大可以自动转换,从大到小需要进行类型强制转换(cast)
boolean类型会在编译时期被JVM转换为int,true为常量值1,false为0,如
boolean a = true;
查看字节码(javap -verbose xxx.class)会发现iconst_1指令,是指把int常量值1压入栈中,因此boolean需要4个字节进行存储。使用int的原因是对于当下32位的处理器(CPU)来说,一次处理数据是32位。而boolean数组会被编译为byte数组,故作为数组时,数组中的每个boolean元素只占一个字节。
基本类型都有对应的包装类型,基本类型与包装类型之间的转换自动装箱与拆箱完成:
Integer a = 5; // 装箱调用Integer.valueOf(2)
int b = a; // 拆箱调用Integer.intValue()
在 Java 8 中,大部分基本类型都有缓存值,如Integer通过其内部类IntegerCache的cache[]缓存了-128~127范围值。
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
...
}
当使用装箱方式初始化Integer时,若初始值是在缓存范围内,则会引用缓存范围内的对象。从上源码注释可以看出,Integer可以通过在启动jvm时添加-XX:AutoBoxCacheMax=<size>
设置其缓存大小,但其它基本类型是没有相应的设置方式的。
Integer a = 5;
Integer b = 5;
System.out.println(a==b); //true
b = new Integer(5); // 为5分配了新的空间,所以与缓存5的空间地址不同
System.out.println(a==b); //false
a = 255;
b = 255;
System.out.println(a==b); //false
各基本类型对应包装类型的缓存池值(Double、Float没有缓存)如下:
- Boolean: 通过字段缓存true,false
- Byte:内部类ByteCache缓存所有字节(-127-128)
- Short:内部类ShortCache缓存-127-128
- Integer:内部类IntegerCache缓存-127-128
- Long:内部类LongCache缓存-127-128
- Character:内部类CharacterCache缓存0~127对应的ASCII码字符值
从字节数解读不同位运算
char a = 'a'; // 'a'的ASCII码为97
int b = 13;
long e = a + d;
那么问题来了,e是多少呢?运算过程中类型是怎么转换的呢?请务必让我根据下图一一讲解:
(上图为在类编译结果目录target/pagkage执行javap -verbose Test显示的字节码)- bipush将a转换为int值('a'对应的ASCII码值)入栈,istore_1取出栈顶int值(即a值)保存到局部变量1中
- bipush将b(b本身为int,无需转换)入栈,istore_2取出栈顶int值(即b值)保存到局部变量2中
- iload_1、iload_2将局部变量1、2的int类型值入栈,iadd将栈顶的2个int值相加,并将结果压栈,i2l将int转long(不是i2十一哦),然后lstore_3将栈顶long值保存到局部变量3中
如果你问我知道这些有什么用?第一反应肯定是装逼啊[doge],当然对基本数据类型的运算了解肯定也会加深啦。