Long
Long 类将基本类型 long 的值包装在对象中。 Long 类型的对象包含一个类型为 long 的属性。
另外,提供了几种将 long 转换为 String 和 String 转换为 long 的方法,以及其他在处理 long 类型时有用的方法。
Long 类被 final 关键字修饰,不能被继承。Long 类继承自 Number 类,实现了 Comparable 、 Constable 、 ConstantDesc 接口。
public final class Long extends Number implements Comparable<Long>, Constable, ConstantDesc {
private final long value;
@Native public static final long MIN_VALUE = 0x8000000000000000L;
@Native public static final long MAX_VALUE = 0x7fffffffffffffffL;
@Native public static final int SIZE = 64;
public static final int BYTES = SIZE / Byte.SIZE;
public static final Class<Long> TYPE = (Class<Long>) Class.getPrimitiveClass("long");
}
value 为常量,用于保存 Long 对象所对应的基本类型 long 的值。
SIZE 为静态常量,用于表示二进制补码形式的 long 类型所需要的位数。
BYTES 为静态常量,用于表示二进制补码形式的 long 值所占的字节数。即8个字节。
TYPE 为静态常量,基本类型 long 的 Class 对象。
MIN_VALUE 为静态常量, long 型所能表示的最小数 263-1 。
MAX_VALUE 为静态常量, long 型所能表示的最小数 -263 。
@Native 指示可以从本地代码引用定义常量值的字段。
Long 类的构造方法很少使用,并且官方不推荐使用,推荐使用 valueOf(long) 方法。
LongCache
静态内部类,并且是私有的。定义了一个静态常量数组 cache 用来存储 Long 类 [-128, 127] 区间中的值。
在类中使用静态代码块初始化 cache 的值,size 的大小即为[-128, 127] 区间中的值的数量,共256个。然后依次创建这些对象,并将其保存在 cache 中。避免了重复的创建对象,方便调用和回收。
注意:静态代码块只在类加载的时候执行一次。
private static class LongCache {
private LongCache() {
}
static final Long[] cache;
static Long[] archivedCache;
static {
int size = -(-128) + 127 + 1;
// Load and use the archived cache if it exists
VM.initializeFromArchive(LongCache.class);
if (archivedCache == null || archivedCache.length != size) {
Long[] c = new Long[size];
long value = -128;
for(int i = 0; i < size; i++) {
c[i] = new Long(value++);
}
archivedCache = c;
}
cache = archivedCache;
}
}
toString(long)
返回表示指定整数的 String 对象。该参数将转换为带符号的十进制表示形式,并作为字符串返回。
public static String toString(long i) {
int size = stringSize(i);
if (COMPACT_STRINGS) {
byte[] buf = new byte[size];
getChars(i, size, buf);
return new String(buf, LATIN1);
} else {
byte[] buf = new byte[size * 2];
StringUTF16.getChars(i, size, buf);
return new String(buf, UTF16);
}
}
- 调用 stringSize(long) 方法计算字符串长度。
- 根据 COMPACT_STRINGS 的值,对字符串采用不同的编码。
- 创建大小为 size 的 byte[] ,调用 getchars(int, int, byte[]) 方法(见下文)将数字以十进制将每一位保存在 byte[] 中。
- 调用 String 的构造方法,并使用 byte[] 对字符串初始化。
static final boolean COMPACT_STRINGS;
static {
COMPACT_STRINGS = true;
}
COMPACT_STRINGS 定义在 String 类中,并在静态代码块中初始化为 true 。表示该字符串是否可以被压缩,用于具有多个可能实现路径的方法。(java 9 新特性)
这个字段的实际值是由JVM注入的。静态初始化块用于设置这里的值,以表明这个静态final字段不可静态折叠,并避免在vm初始化期间任何可能的循环依赖。
实例字段值通常对于优化JIT编译器是不透明的。因此,在性能敏感的地方,首先检查静态布尔 COMPACT_STRINGS,然后再检查编码器字段
Latin1是ISO-8859-1的别名,有些环境下写作Latin-1。ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。
ISO-8859-1收录的字符除ASCII收录的字符外,还包括西欧语言、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。ASCII编码是一个7位的容器,ISO-8859-1编码是一个8位的容器。
stringSize(long)
返回给定 long 值的字符串表示所需要的长度。
-
如果 x 为负数,d 等于1;否则,d 等于0。因为如果 x 为负数,字符串的第一个字符应该为 ‘-’。
-
如果 x 是正数,将 x 装换成负数进行计算,方法如下:
-
判断 x 是否大于 -10 ,如果大于,说明 x 在区间 [-9, 0] 之间。即 x 只有1位。
-
如果 x 小于 -10,则给 -10×10,比较 x 与 -100 的大小,依次类推……
-
求出数字所需要的位数,加上符号位 d 的长度,即为字符串所需要的长度。
static int stringSize(long x) {
int d = 1;
if (x >= 0) {
d = 0;
x = -x;
}
long p = -10;
for (int i = 1; i < 19; i++) {
if (x > p)
return i + d;
p = 10 * p;
}
return 19 + d;
}
getChars(long, int, byte[])
将代表整数 i 的字符放入字符数组 buf 。字符从指定索引处的最低有效数字(不包括最高字符)开始向前放置
static int getChars(long i, int index, byte[] buf) {
long q;
int r;
int charPos = index;
boolean negative = (i < 0);
if (!negative) {
i = -i;
}
// Get 2 digits/iteration using longs until quotient fits into an int
while (i <= Integer.MIN_VALUE) {
q = i / 100;
r = (int)((q * 100) - i);
i = q;
buf[--charPos] = Integer.DigitOnes[r];
buf[--charPos] = Integer.DigitTens[r];
}
// Get 2 digits/iteration using ints
int q2;
int i2 = (int)i;
while (i2 <= -100) {
q2 = i2 / 100;
r = (q2 * 100) - i2;
i2 = q2;
buf[--charPos] = Integer.DigitOnes[r];
buf[--charPos] = Integer.DigitTens[r];
}
// We know there are at most two digits left at this point.
q2 = i2 / 10;
r = (q2 * 10) - i2;
buf[--charPos] = (byte)('0' + r);
// Whatever left is the remaining digit.
if (q2 < 0) {
buf[--charPos] = (byte)('0' - q2);
}
if (negative) {
buf[--charPos] = (byte)'-';
}
return charPos;
}
- 如果整数 i 是正数,将其转换为负数。
- 当 i 小于100时,每次对 i 除以 100,然后再乘以100,减去 i ,可以得到 i 除 100 的余数 r,通过数组 DigitOnes 和 DigitTens 分别取到 r 的个位和十位存到数组 buf 中,依此循环。
- 当 i 大于100 时,不能直接通过数组 DigitOnes 和 DigitTens 获得数字,因为不能确定此时 i 的位数。所以对 i 除 10 求余数将其存放再数组 buf 中,如果 q 仍小于 0,说明最高位就是 q ,将其保存再数组 buf 中。
- 根据符号标志 negative 判断数字是否为负数,如果是负数,则在 buf 数