目录
Byte、Short、Integer、Double 的常量池源码(以 Byte为例)
注:手机端浏览本文章可能会出现 “目录”无法有效展示的情况,请谅解,点击侧栏目录进行跳转
前言
在实际开发过程中,我们经常会遇到需要使用对象,而不是内置(基本)数据类型的场景。
为了解决这个问题,Java 语言为每一个内置(基本)数据类型提供了对应的包装类。
Number 类
基本数据类型 | 包装类 |
---|---|
boolean(未定) | Boolean |
byte(1字节) | Byte |
short(2字节) | Short |
int(4字节) | Integer |
long(8字节) | Long |
char(2字节) | Charter |
float(4字节) | Float |
double(8字节) | Double |
所有的包装类(Byte、Short、Integer、Long、Float、Double)都是抽象类 Number 的子类。
将基本数据类型转换为它们对应的引用类型称为 “装箱”,当内置(基本)数据类型被当作对象使用的时候,编译器会把内置(基本)类型装箱为 “包装类”;相反,编译器也可以把一个对象拆箱为内置(基本)数据类型。Number 类属于 java.lang 包。
Number 类方法
序号 | 方法及描述 |
---|---|
1 | Number 对象.xxxValue() 将 Number 对象转换为 xxx 数据类型的值并返回 |
2 | Number 对象.compareTo(参数) 将 Number 对象与参数比较 |
3 | Number 对象.equals(参数) 判断 Number 对象是否与参数相等 |
4 | 包装类型.valueOf(参数) 将参数转换为 Number 对象 |
5 | Number 对象.toString() 以字符串形式返回值 |
6 | Integer.parseInt(String 类型参数) 将字符串解析为 int 类型 |
7 | Number 对象.hashCode() 返回此 Number 对象的哈希码值 |
8 | Number 对象.getClass() 返回此 Number 对象的运行时类 |
Byte、Short、Integer、Double 的常量池源码(以 Byte为例)
public final class Byte extends Number implements Comparable<Byte> {
//...
private static class ByteCache {
private ByteCache(){}
static final Byte cache[] = new Byte[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Byte((byte)(i - 128));
}
}
public static Byte valueOf(byte b) {
final int offset = 128;
return ByteCache.cache[(int)b + offset];
}
//...
}
解读:
- ByteCache 是一个私有静态内部类,用于维护 byte 类型的常量池。其中 cache 数组用于缓存字节值在范围 -128 到 127 之间的 Byte 对象。
- 在静态初始化块中,通过循环遍历范围内的所有可能的bye 值,创建对应的 Byte 对象存储在 cache 数组中。由于 byte 的取值范围是 -128 到 127,因此数组的长度是 256。
- valueOf(byte b)方法用于获取指定字节值对应的 Byte 对象。它会将传入的 byte 值加上偏移量 128,然后从 ByteCache 的 cache 数组中获取对应位置的 Byte 对象并返回。
测试用例一
Integer n1 =33;
Integer n2 =33;
System.out.print(n1 == n2);//使用缓存,同一内存地址,输出true
测试用例二
Integer n3 =333;
Integer n4 =333;
System.out.print(n3 ==n4);//超出缓存范围,重新分配内存地址,输出false
测试用例三
Integer n5 =40;
Integer n6 = new Integer(40);
System.out.print(n5 == n6);//n6使用 new Integer创建对象,未使用缓存,输出false
Character 类
Character 类方法
序号 | 方法及描述 |
---|---|
1 | Character.isLetter(Character 对象) 判断是否是一个字母 |
2 | Character.isDigit(Character 对象) 判断是否是一个数字字符 |
3 | Character.isWhitespace(Character 对象) 判断是否是一个空白字符 |
4 | Character.isUpperCase(Character 对象) 判断是否是大小字母 |
5 | Character.isLowerCase(Character 对象) 判断是否是小写字母 |
6 | Character 对象.toUpperCase() 转换成大写形式 |
7 | Character 对象.toLowerCase() 转换成小写形式 |
8 | Character 对象.toString() 返回字符的字符串形式 |
Character 的常量池源码
public final class Character implements java.io.Serializable, Comparable<Character> {
// ...
private static class CharacterCache {
private CharacterCache() {}
static final Character[] cache = new Character[127 + 1];
static {
for (int i = 0; i < cache.length; i++) {
cache[i] = new Character((char) i);
}
}
}
// ...
public static Character valueOf(char c) {
if (c <= 127) { // ASCII 字符范围
return CharacterCache.cache[(int) c];
} else {
return new Character(c);
}
}
// ...
}
解读:
- CharacterCache 是一个私有静态内部类,负责维护字符常量池(cache 数组)。
- 在类初始化时,会遍历 ASCII 字符范围(0-127),创建相应的 Character 对象并存储在 cache 数组中。
- valueOf(char c)方法是获取指定字符对应的 Character 对象的静态工厂方法。
- 当传入的字符在 ASCII 字符范围内时,会直接从常量池中返回对应的缓存对象。
- 如果不在范围内,则会创建一个新的 Character 对象。
- 通过常量池技术,可以避免重复创建相同的字符对象,提高性能和节省内存。
总结
- 将基本类型转换为它们对应的引用类型为 “装箱”;
- 将包装类型转换为基本数据类型为 “拆箱”;
- 基本数据类型 与 它们的包装类型不同的是:包装类型可以引用 Null ,基本数据类型不行;
- Byte、Short、Integer、Long 的创建范围在 -128 到 127 的缓存数据;
- Character 创建范围在 0 到 127 的缓存数据;
- 如果数据处于缓存范围,不会重新创建对象,直接从缓存中获取;
- 如果数据超出缓存范围,才会创建对象,减少对象重复创建所带来的内存与性能开销;