包装类型
973字约3分钟
2024-08-08
引用类型可以赋值为 null
,表示空,但基本类型不能赋值为 null
,我们可以定义一个包装基本类型的类
包装类型
基本类型 | 对应的引用类型 |
---|---|
boolean | java.lang.Boolean |
byte | java.lang.Byte |
short | java.lang.Short |
int | java.lang.Integer |
long | java.lang.Long |
float | java.lang.Float |
double | java.lang.Double |
char | java.lang.Character |
使用
Java
核心库为每种基本类型都提供了对应的包装类型,我们可以直接使用
public static void main(String[] args) {
int i = 100;
// 通过 new 操作符创建Integer实例(不推荐使用,会有编译警告)
Integer n1 = new Integer(i);
// 通过静态方法 valueOf(int) 创建 Integer 实例
Integer n2 = Integer.valueOf(i);
// 通过静态方法 valueOf(String) 创建 Integer 实例
Integer n3 = Integer.valueOf("100");
// 通过 intValue 方法转为 int
int i1 = n3.intValue();
}
Auto Boxing
Java
编译器帮助我们自动在 int
和 Integer
之间转型
public static void main(String[] args) {
// 编译器自动使用 Integer.valueOf(int)
Integer integer = 100;
// 编译器自动使用 Integer.intValue()
int i = integer;
}
这种直接把 int
变为 Integer
的赋值写法,称为自动装箱(Auto Boxing
),反过来,把 Integer
变为 int
的赋值写法,称为自动拆箱(Auto Unboxing
)
注意
自动装箱和自动拆箱只发生在编译阶段,目的是为了少写代码。
装箱和拆箱会影响代码的执行效率,因为编译后的
class
代码是严格区分基本类型和引用类型的。并且,自动拆箱执行时可能会报NullPointerException
不变类
所有的包装类型都是不变类。我们查看 Integer
的源码可知,一旦创建了 Integer
对象,该对象就是不变的
public final class Integer {
private final int value;
}
比较
对两个 Integer
实例进行比较要特别注意:绝对不能用 ==
比较,因为 Integer
是引用类型,必须使用 equals()
比较
public static void main(String[] args) {
Integer i1 = 127;
Integer i2 = 128;
Integer i3 = new Integer(127);
Integer i4 = Integer.valueOf(127);
Integer i5 = new Integer(128);
Integer i6 = Integer.valueOf(128);
// false,new 操作就是创建一个新对象,所以引用地址不同
System.out.println(i1 == i3);
// true,Integer.valueOf() 方法点开源码就知道,-128 到 127 是静态缓存值
// if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)];
System.out.println(i1 == i4);
// false,new 操作就是创建一个新对象,所以引用地址不同
System.out.println(i2 == i5);
// false,超出静态缓存值范围,也是创建的新对象
System.out.println(i2 == i6);
// false,都是两个不同的对象
System.out.println(i5 == i6);
// 结果均为 true,equals() 方法就是比较值的大小
System.out.println(i1.equals(i3));
System.out.println(i1.equals(i4));
System.out.println(i2.equals(i5));
System.out.println(i2.equals(i6));
System.out.println(i5.equals(i6));
}
进制转换
Integer
类本身还提供了大量方法,例如,最常用的静态方法 parseInt()
可以把字符串解析成一个整数
int x1 = Integer.parseInt("100"); // 100
int x2 = Integer.parseInt("100", 16); // 256,因为按16进制解析
Integer
还可以把整数格式化为指定进制的字符串
public static void main(String[] args) {
System.out.println(Integer.toString(100)); // "100",表示为10进制
System.out.println(Integer.toString(100, 36)); // "2s",表示为36进制
System.out.println(Integer.toHexString(100)); // "64",表示为16进制
System.out.println(Integer.toOctalString(100)); // "144",表示为8进制
System.out.println(Integer.toBinaryString(100)); // "1100100",表示为2进制
}
Java
的包装类型还定义了一些有用的静态变量
// boolean只有两个值true/false,其包装类型只需要引用Boolean提供的静态字段:
Boolean t = Boolean.TRUE;
Boolean f = Boolean.FALSE;
// int可表示的最大/最小值:
int max = Integer.MAX_VALUE; // 2147483647
int min = Integer.MIN_VALUE; // -2147483648
// long类型占用的bit和byte数量:
int sizeOfLong = Long.SIZE; // 64 (bits)
int bytesOfLong = Long.BYTES; // 8 (bytes)
所有的整数和浮点数的包装类型都继承自 Number
,因此,可以非常方便地直接通过包装类型获取各种基本类型
// 向上转型为Number:
Number num = new Integer(999);
// 获取byte, int, long, float, double:
byte b = num.byteValue();
int n = num.intValue();
long ln = num.longValue();
float f = num.floatValue();
double d = num.doubleValue();