java源码分析---Long类(JDK14)


更多源码分析,请点击


Long

Long 类将基本类型 long 的值包装在对象中。 Long 类型的对象包含一个类型为 long 的属性。

另外,提供了几种将 long 转换为 StringString 转换为 long 的方法,以及其他在处理 long 类型时有用的方法。

Long 类被 final 关键字修饰,不能被继承。Long 类继承自 Number 类,实现了 ComparableConstableConstantDesc 接口。

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 为静态常量,基本类型 longClass 对象。

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 的值,对字符串采用不同的编码。
  • 创建大小为 sizebyte[] ,调用 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,通过数组 DigitOnesDigitTens 分别取到 r 的个位和十位存到数组 buf 中,依此循环。
  • 当 i 大于100 时,不能直接通过数组 DigitOnesDigitTens 获得数字,因为不能确定此时 i 的位数。所以对 i 除 10 求余数将其存放再数组 buf 中,如果 q 仍小于 0,说明最高位就是 q ,将其保存再数组 buf 中。
  • 根据符号标志 negative 判断数字是否为负数,如果是负数,则在 buf
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值