所有包装类都被final
修饰,具备拆箱和装箱的性质,提供了一些常规方法。
下文以Integer
作为举例
存储区域的不同
基本数据类型的局部变量存储在栈中
基本数据类型的成员变量或基本数据类型的数组存储在堆中。
但这并不绝对,如果JVM开启了逃逸分析(Escape Analysis)的话,发现有些对象没有逃逸出方法,那么有可能堆内存分配会被优化成栈内存分配(标量替换)。
包装类存储在堆中
装箱/拆箱
装箱指的是基本数据类型转换为其包装类型
拆箱指的是包装类型转换为其基本数据类型
Integer i = 1; // 自动装箱 Integer.valueOf(1)
Integer i2 = new Integer(1); // 手动装箱
int i3 = i2; // 自动拆箱 i2.intValue()
int i4 = i2.intValue(); // 手动拆箱
i = i + 1; // Integer.valueOf(i.intValue() + 1) 先将i拆箱成基本数据类型进行计算再将计算结果装箱
包装类型的缓存池
对于Byte、Short、Integer、Long
这四个包装类型都有维护缓存池,其值为-128~127
Byte -> private static class ByteCache
Short -> private static class ShortCache
Integer -> private static class IntegerCache
Long -> private static class LongCache
对于Character
缓存了0~127
之间字符对应的ASCII码
Character -> private static class CharacterCache
对于Boolean
则维护了两个true/false
常量
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
Float、Double
没有缓存池
基本数据类型与包装类型的比较
int i = 1;
int i2 = 128;
Integer i3 = 1;
Integer i4 = 128;
Integer i5 = 1;
Integer i6 = 128;
Integer i7 = new Integer(1);
System.out.println(i == i3); // true i == i3.intValue()
System.out.println(i2 == i4); // true i2 == i4.intValue()
System.out.println(i3 == i5); // true Integer.valueOf(i3) == Integer.valueOf(i5)
System.out.println(i4 == i6); // false Integer.valueOf(i3) == Integer.valueOf(i5) 超出缓存池的范围了,两个对象
System.out.println(i == i7); // true i == i7.intValue()
System.out.println(i3 == i7); // false 右边new了个新对象
int
与Integer
(就算是new Integer
)相比,Integer对象会调用intValue()
方法拆箱再进行比较,所以恒为trueInteger
与Integer
相比,因为Integer i3 = 1 => Integer.valueOf(1)
会经历自动装箱,而Integer.valueOf()
会进行缓存区的判断,如果在缓存区域范围内则为true,如果不在缓存区域内其实是new Integer()
即为falseInteger
和new Integer
,如果在缓存区域范围内则Integer
指向的是常量池,而new Integer
指向的是堆,如果不在缓存池范围内,则两边都是new Integer
,堆内存地址肯定不一样,即恒为false+
这个运算符不适用于Integer对象,所以针对包装类型会进行拆箱操作
valueOf() 方法
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
与字符串的转换方法
String.valueOf(10); // 基本数据类型转字符串
Integer.parseInt("10"); // 字符串转基本数据类型
Integer.valueOf("10"); // 字符串转包装类型
getInteger() 方法的坑
这里不是将字符串转化为Integer!! 不要顺手就写这个了
Integer.getInteger(""); // 确定具有指定名称的系统属性的整数值
认识下NaN
和INFINITY
NaN
和INFINITY
只存在于浮点数运算中
/**
* A constant holding the positive infinity of type
* {@code double}. It is equal to the value returned by
* {@code Double.longBitsToDouble(0x7ff0000000000000L)}.
*/
public static final double POSITIVE_INFINITY = 1.0 / 0.0;
/**
* A constant holding the negative infinity of type
* {@code double}. It is equal to the value returned by
* {@code Double.longBitsToDouble(0xfff0000000000000L)}.
*/
public static final double NEGATIVE_INFINITY = -1.0 / 0.0;
/**
* A constant holding a Not-a-Number (NaN) value of type
* {@code double}. It is equivalent to the value returned by
* {@code Double.longBitsToDouble(0x7ff8000000000000L)}.
*/
public static final double NaN = 0.0d / 0.0;
-
NaN表示非数字,他不与任何数相等,甚至不等于他自己
System.out.println((0.0 / 0.0)); // NaN System.out.println((0.0 / 0.0) == (0.0 / 0.0)); // false
-
INFINITY表示无限
System.out.println(1.0/0.0); // INFINITY 正无穷大 System.out.println(-1.0/0.0); // -INFINITY 负无穷大
-
INFINITY除以0等于NAN
-
INFINITY除以非0的数还是INFINITY