基本数据类型
Java 中有 8 种基本数据类型,分别为:
- 6中数字类型:
- 4种整数类型:
byte
、short
、int
、long
- 2种浮点型:
float
、double
- 4种整数类型:
- 1种字符类型:
char
- 1种布尔型:
boolean
基本类型 | 位数 | 字节 | 默认值 | 取值范围 |
---|---|---|---|---|
byte | 8 | 1 | 0 | -128 ~ 127 |
short | 16 | 2 | 0 | -32768 ~ 32767 |
int | 32 | 4 | 0 | -2147483648 ~ 2147483647 |
long | 64 | 8 | 0L | -9223372036854775808 ~ 9223372036854775807 |
char | 16 | 2 | ’u0000‘ | 0 ~ 65535 |
float | 32 | 4 | 0f | 1.4E-45 ~ 3.4028235E38 |
double | 64 | 8 | 0d | 4.9E-324 ~ 1.7976931348623157E308 |
boolean | 1 | false | ture/false |
对应的包装类分别为:Byte
、Short
、Integer
、Long
、Float
、Double
、Boolean
、Character
。
基本类型和包装类型的区别
- 成员变量包装类型不赋值就是
null
,而基本类型有默认值且不是null
。 - 包装类型可用于泛型,而基本类型不可以。
- 基本数据类型的局部变量存放在 Java 虚拟机栈中的局部变量表中,基本数据类型的成员变量(未被 static 修饰 )存放在 Java 虚拟机的堆中。包装类型属于对象类型,我们知道几乎所有对象实例都存在于堆中。
- 相比于对象类型, 基本数据类型占用的空间非常小。
注意:基本数据类型存放在栈中是一个常见的误区! 基本数据类型的成员变量如果没有被 static 修饰的话(不建议这么使用,应该要使用基本数据类型对应的包装类型),就存放在堆中。
包装类的缓存机制
Java 基本数据类型的包装类的大部分都用到了缓存机制来提升性能。
Byte
,Short
,Integer
,Long
这4种包装类默认创建了数值[-128, 127]的相应类型的缓存数据,Character
创建了数值在[0, 127]范围的缓存数据,Boolean
直接返回 True
或者 False
。如果超出对应范围仍然会去创建新的对象,缓存的范围区间的大小只是在性能和资源之间的权衡。
两种浮点数类型的包装类 Float
,Double
并没有实现缓存机制。
自动装箱与拆箱的原理
- 自动装箱:将基本类型用他们对应的引用类型包装起来;
- 自动拆箱:将包装类型转换为基本数据类型。
装箱实质上就是调用了包装类的valueOf()
方法,拆箱实际上调用了 xxxValue()
方法。即:
Integer i = 10
等价于Integer i = Integer.valueOf(10)
;int n = i
则等价于int n = i.intValue()
;
注意:如果频繁拆装箱的话,也会严重影响系统的性能。我们应该尽量避免不必要的拆装箱操作。
浮点数运算时会有丢失精度的风险
float a = 2.0f - 1.9f;
float b = 1.8f - 1.7f;
System.out.println(a);// 0.100000024
System.out.println(b);// 0.099999905
System.out.println(a == b);// false
计算机底层都是二进制的,且计算机在表示一个数字时,宽度是有限的,无限循环的小数存储在计算机时,只能被截断,所以就会导致小数精度发生损失的情况。这也就是解释了为什么浮点数没有办法用二进制精确表示。
BigDecimal
BigDecimal
可以规避浮点数运算时精度损失的风险。通常情况下,大部分需要浮点数精确运算结果的业务场景(比如涉及到钱的场景)都是通过 BigDecimal
来做的。
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");
BigDecimal x = a.subtract(b);
BigDecimal y = b.subtract(c);
System.out.println(x); /* 0.1 */
System.out.println(y); /* 0.1 */
System.out.println(Objects.equals(x, y)); /* true */
超过 long 整型的数据表示
基本数值类型都有一个表达范围,如果超过这个范围就会有数值溢出的风险。在 Java 中,64 位 long 整型是最大的整数类型。
BigInteger
内部使用 int[]
数组来存储任意大小的整形数据。相对于普通整数类型的运算来说,BigInteger
运算效率较低。