public final class Long extends Number implements Comparable<Long> {
/*
* 继承Number类提供将表示的数值转换为 byte、double、float、int、long 和 short 的方法。<br />
* 实现Comparable接口,获取到compareTo方法。
*/
// 保持 long 类型的最小值的常量,该值为 -2的63方
public static final long MIN_VALUE = 0x8000000000000000L;
// 保持 long 类型的最大值的常量,该值为 2的63方-1
public static final long MAX_VALUE = 0x7fffffffffffffffL;
// 表示基本类型 long 的 Class 实例
public static final Class<Long> TYPE = (Class<Long>) Class.getPrimitiveClass("long");
/**
* 转化对应进制的数字为十进制
* @param i 要转换为字符串的 long
* @param radix 进制数
* @return String
*/
public static String toString(long i, int radix) {
// 如果进制数小于2进制 或者大于 26进制,则改用十进制。
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
radix = 10;
/* 如果是十进制,用最快的版本 */
if (radix == 10)
return toString(i);
// 创建一个65位的字符数组(负数时:1位符号位+64位数字;正数时,64位数字)
char[] buf = new char[65];
int charPos = 64;
boolean negative = (i < 0);
// 将正数转为负数进行运算,防止负数转为正数的溢出情况
if (!negative) {
i = -i;
}
// 循环判断当前转换的字符是否小于计数的相反数
while (i <= -radix) {
//根据余数的相反数在digits数组中获取相应的字符,倒序存放到buf[]数组里
buf[charPos--] = Integer.digits[(int)(-(i % radix))];
i = i / radix;
}
buf[charPos] = Integer.digits[(int)(-i)];
// 若是负数,加减号
if (negative) {
buf[--charPos] = '-';
}
// 返回一个字符串,参数为char数组、起始位置、字符长度
return new String(buf, charPos, (65 - charPos));
}
/**
* 返回当前long的16进制的字符串形式
* @param i 要转换为字符串的 long
* @return String
*/
public static String toHexString(long i) {
return toUnsignedString(i, 4);
}
/**
* 返回当前long的8进制的字符串形式
* @param i 要转换为字符串的 long
* @return String
*/
public static String toOctalString(long i) {
return toUnsignedString(i, 3);
}
/**
* 返回当前long的2进制的字符串形式
* @param i 要转换为字符串的 long
* @return String
*/
public static String toBinaryString(long i) {
return toUnsignedString(i, 1);
}
/**
* 返回当前long类型的i的shift进制的字符串形式的私有工具类
* @param i
* @param shift 进制数
* @return String
*/
private static String toUnsignedString(long i, int shift) {
char[] buf = new char[64];
int charPos = 64;
// 算数左移,radix中间变量用于计算mask
int radix = 1 << shift;
// mask掩码用于获取i的shift位低位,mask二进制数每一位都是1
long mask = radix - 1;
do {
//取出i二进制数低位shift位,将对应的字符存入buf
buf[--charPos] = Integer.digits[(int)(i & mask)];
//逻辑右移,剔除已取出的shfit位低位
i >>>= shift;
} while (i != 0);
return new String(buf, charPos, (64 - charPos));
}
/**
* 返回当前long的字符串形式
* @param i
* @return String
*/
public static String toString(long i) {
if (i == Long.MIN_VALUE)
return "-9223372036854775808";
// 判断是否为负数,计算长度
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] buf = new char[size];
// 将数字分成一个个char,保存到buf数组中
getChars(i, size, buf);
return new String(buf, true);
}
/**
* 将某个long型数值写入到字符数组中(若i等于Long.MIN_VALUE,则为失败)
* 几种运算的耗时长短:除法运算>乘法运算>移位结合加法的运算
* @param i long型数值
* @param index 长度
* @param buf buf数组
* @return void
*/
static void getChars(long i, int index, char[] buf) {
long q;
int r;
int charPos = index;
char sign = 0;
// 负数的处理
if (i < 0) {
sign = '-';
i = -i;
}
// i大于int最大值
while (i > Integer.MAX_VALUE) {
q = i / 100;
// really: r = i - (q * 100);
r = (int)(i - ((q << 6) + (q << 5) + (q << 2)));
// 将商赋给i,继续循环,直到小于2147483647
i = q;
// 取DigitOnes[r]的值其实取数字r%10的结果
buf[--charPos] = Integer.DigitOnes[r];
// 取DigitTens[r]的值其实取数字r/10的结果
buf[--charPos] = Integer.DigitTens[r];
}
// i大于等于65536,16次方
int q2;
int i2 = (int)i;
while (i2 >= 65536) {
q2 = i2 / 100;
// really: r = i2 - (q * 100);
r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2));
// 将商赋给i,继续循环,直到小于65536
i2 = q2;
// 取DigitOnes[r]的值其实取数字r%10的结果
buf[--charPos] = Integer.DigitOnes[r];
// 取DigitTens[r]的值其实取数字r/10的结果
buf[--charPos] = Integer.DigitTens[r];
}
// 对于较小的数字,进入快速模式
// 循环存放低两字节的数字存放到字符数组中空余位置
for (;;) {
// 右移19位
/**
* >>>: 无符号的右移
* >>: 有符号的右移
*/
q2 = (i2 * 52429) >>> (16+3);
r = i2 - ((q2 << 3) + (q2 << 1)); // r = i2-(q2*10) ...
// 从digit数组中取数
buf[--charPos] = Integer.digits[r];
i2 = q2;
//整数写入字符数组完成
if (i2 == 0) break;
}
//整数写入字符数组完成
if (sign != 0) {
buf[--charPos] = sign;
}
}
/**
* 判断一个long类型数字的长度
* @param x long类型的整数
* @return int
*/
static int stringSize(long x) {
long p = 10;
for (int i=1; i<19; i++) {
if (x < p)
return i;
p = 10*p;
}
return 19;
}
/**
* 返回输入字符串的指定进制的long值
* @param s
* @param radix 进制数
* @throws NumberFormatException
* @return long
*/
public static long parseLong(String s, int radix)
throws NumberFormatException
{
if (s == null) {
throw new NumberFormatException("null");
}
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}
// 保存结果
long result = 0;
// 判断正负
boolean negative = false;
int i = 0, len = s.length();
long limit = -Long.MAX_VALUE;
long multmin;
int digit;
if (len > 0) {// 字符串的长度大于零
// 取第一个值
char firstChar = s.charAt(0);
if (firstChar < '0') { // 如果第一个字符小于0
if (firstChar == '-') {// 为负数
negative = true;
limit = Long.MIN_VALUE;
} else if (firstChar != '+')//不为正数
throw NumberFormatException.forInputString(s);
if (len == 1) // 不能只有一个符号
throw NumberFormatException.forInputString(s);
i++;
}
// 限制的最小值(在对应进制的)
multmin = limit / radix;
// 将字符串的数字部分转为进制的数字(从左到右)
while (i < len) {
// 将字符串的数字部分的一个数字(对应进制),通过Character类转为进制的数
// 若字符串中的某一个字符,在字符串进制下(radix)是无效的,则返回-1
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {// 若返回-1(无效)
throw NumberFormatException.forInputString(s);
}
if (result < multmin) {// 结果小于最小的值(目标进制下)
throw NumberFormatException.forInputString(s);
}
// 结果:将结果乘上字符串进制数
result *= radix;
// 若结果小于最小值加上当前最字符值
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
// 将结果减去当前字符的值
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
// 若是负数,则直接返回,若是正数,先取反结果再输出
return negative ? result : -result;
}
/**
* 返回指定字符串的long类型的数值,默认是10进制的
* @param s long类型的数值
* @throws NumberFormatException
* @return long
*/
public static long parseLong(String s) throws NumberFormatException {
return parseLong(s, 10);
}
/**
* 返回指定转换进制的字符串的一个Long对象
* @param s 需要转换的字符串
* @param radix 进制数
* @throws NumberFormatException
* @return Long
*/
public static Long valueOf(String s, int radix) throws NumberFormatException {
return Long.valueOf(parseLong(s, radix));
}
/**
* 返回指定字符串的一个Long对象,默认是10进制的
* @param s 需要转换的字符串
* @throws NumberFormatException
* @return Long
*/
public static Long valueOf(String s) throws NumberFormatException
{
return Long.valueOf(parseLong(s, 10));
}
/**
* 缓存以支持自动装箱的对象标识语义.用于在-128和127
* 缓存在第一次使用时被初始化。
*/
private static class LongCache {
private LongCache(){}
static final Long cache[] = new Long[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Long(i - 128);
}
}
/**
* 返回表示指定 long 值的 Long 实例。
* 如果不需要新的 Long 实例,则通常优先使用此方法,
* 而不是使用构造方法 Long(long),
* 因为此方法通过缓存频繁请求的值,
* 可以显著提高时间和空间性能。
* @param l
* @return Long
*/
public static Long valueOf(long l) {
final int offset = 128;
// 直接获得在[-128,127]范围内的LongCache缓存的对象,不在该范围则重新实例化Integer对象
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
/**
* 将 String 解码成 Long
* @param nm 字符串
* @throws NumberFormatException
* @return Long
*/
public static Long decode(String nm) throws NumberFormatException {
// 10进制
int radix = 10;
int index = 0;
// 正负数标识
boolean negative = false;
Long result;
if (nm.length() == 0)
throw new NumberFormatException("Zero length string");
// 获取第一个字符
char firstChar = nm.charAt(0);
if (firstChar == '-') {// 为负数
negative = true;
index++;
} else if (firstChar == '+')// 为正数
index++;
// 然后剩下的字符串以0x或0X开头,表示十六进制
if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
index += 2;
radix = 16;
}
else if (nm.startsWith("#", index)) {// 或以#开头,表示十六进制
index ++;
radix = 16;
}
//若以0开头,且字符串长度大于当前判断字符数+1,则为8进制
else if (nm.startsWith("0", index) && nm.length() > 1 + index) {
index ++;
radix = 8;
}
// 再存在"-"/"+"这两字符,则抛出数字转化异常
if (nm.startsWith("-", index) || nm.startsWith("+", index))
throw new NumberFormatException("Sign character in wrong position");
try {
// 将剩下的字符串从某进制转为指定进制的数的包装类对象
result = Long.valueOf(nm.substring(index), radix);
// 若是负数,取反包装类Long中的value的值,再进行获取该基本数据类型的包装对象实例
result = negative ? Long.valueOf(-result.longValue()) : result;
} catch (NumberFormatException e) {
// 使用long类型参数转化出现异常,转而使用String类型参数进行转化
String constant = negative ? ("-" + nm.substring(index))
: nm.substring(index);
// 转化字符串成对应的包装类的实例对象
result = Long.valueOf(constant, radix);
}
return result;
}
// 保存Long类中的真实基本数据类型的值
private final long value;
/**
* 构造一个新分配的 Long 对象,它表示指定的 long 值。
* @param value
*/
public Long(long value) {
this.value = value;
}
/**
* 构造新分配的 Long 对象,表示由 String 参数指示的 long 值。
* 该字符串被转换为 long 值,
* 其方式与 radix 参数为 10 的 parseLong 方法所使用的方式一致。
* @param s 要转换为 Long 的 String
* @throws NumberFormatException
* @return void
*/
public Long(String s) throws NumberFormatException {
this.value = parseLong(s, 10);
}
/**
* 以 byte 类型返回该 Long 的值。
*/
public byte byteValue() {
return (byte)value;
}
/**
* 以 short 类型返回该 Integer 的值。
*/
public short shortValue() {
return (short)value;
}
/**
* 以 int 类型返回该 Integer 的值。
*/
public int intValue() {
return (int)value;
}
/**
* 以 long 类型返回该 Integer 的值。
*/
public long longValue() {
return (long)value;
}
/**
* 以 float 类型返回该 Integer 的值。
*/
public float floatValue() {
return (float)value;
}
/**
* 以 double 类型返回该 Integer 的值。
*/
public double doubleValue() {
return (double)value;
}
/**
* 返回表示 Long 值的 String 对象。
* 该值被转换为有符号十进制表示形式,并作为字符串返回,
* 该字符串与用 long 值作为参数的 toString(long) 方法
* 得到的字符串非常相似。
*/
public String toString() {
return toString(value);
}
/**
* 返回 Long 的哈希码。
* 结果是此 Long 对象保持的基本 long 值的两个部分的异或 (XOR)。
*/
public int hashCode() {
return (int)(value ^ (value >>> 32));
}
/**
* 比较此对象与指定对象。当且仅当参数不为 null,
* 并且是一个与该对象包含相同long 值的 Integer 对象时,
* 结果为 true。
*/
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
/**
* 返回系统常量的long值,类似System.getProperty(str);
* @param nm 属性名
* @return Long
*/
public static Long getLong(String nm) {
return getLong(nm, null);
}
/**
* 返回系统常量的long值,类似System.getProperty(str);
* 如果为空,默认值为val
* @param nm 属性名
* @param val 默认值
* @return Long
*/
public static Long getLong(String nm, long val) {
Long result = Long.getLong(nm, null);
return (result == null) ? Long.valueOf(val) : result;
}
/**
* 返回具有指定名称的系统属性的long值。
* @param nm 属性名
* @param val 默认值
* @return Long
*/
public static Long getLong(String nm, Long val) {
String v = null;
try {// 获取对应系统变量名的值
v = System.getProperty(nm);
} catch (IllegalArgumentException e) {
} catch (NullPointerException e) {
}
if (v != null) {
try {//返回字符串中的数字
return Long.decode(v);
} catch (NumberFormatException e) {
}
}
return val;
}
/**
*比较两个 Long 对象的value值大小
*/
public int compareTo(Long anotherLong) {
return compare(this.value, anotherLong.value);
}
/**
* 比较两个long类型的值的大小
* @param x
* @param y
* @return int
*/
public static int compare(long x, long y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
// 用来以二进制补码形式表示 long 值的位数
public static final int SIZE = 64;
/**
* 返回在二进制情况下,i的最高位为1,其他全为0的值。
* 将64位都置为1,然后将该值减去该值右移一位的值
* @param i
* @return long
*/
public static long highestOneBit(long i) {
//右移一位或上原值
i |= (i >> 1);
i |= (i >> 2);
i |= (i >> 4);
i |= (i >> 8);
i |= (i >> 16);
i |= (i >> 32);
//i值减去i右移一位的值
return i - (i >>> 1);
}
/**
* 获取最低位为1,其他位都为0的值
* @param i
* @return long
*/
public static long lowestOneBit(long i) {
// HD, Section 2-1
return i & -i;
}
/**
* 返回i的二进制从头开始有多少个0
* @param i
* @return int
*/
public static int numberOfLeadingZeros(long i) {
//i为0,则有64个0
if (i == 0)
return 64;
int n = 1;
// 使用二分查找(也就是折半查找)思想,
// 看右移16、24、28、30、31位的结果是否为0
int x = (int)(i >>> 32);
if (x == 0) { n += 32; x = (int)i; }
if (x >>> 16 == 0) { n += 16; x <<= 16; }
if (x >>> 24 == 0) { n += 8; x <<= 8; }
if (x >>> 28 == 0) { n += 4; x <<= 4; }
if (x >>> 30 == 0) { n += 2; x <<= 2; }
n -= x >>> 31;
return n;
}
/**
* 返回i的二进制从尾开始有多少个0
* 基于二分查找
* @param i
* @return int 返回类型
*/
public static int numberOfTrailingZeros(long i) {
// HD, Figure 5-14
int x, y;
if (i == 0) return 64;
int n = 63;
y = (int)i; if (y != 0) { n = n -32; x = y; } else x = (int)(i>>>32);
y = x <<16; if (y != 0) { n = n -16; x = y; }
y = x << 8; if (y != 0) { n = n - 8; x = y; }
y = x << 4; if (y != 0) { n = n - 4; x = y; }
y = x << 2; if (y != 0) { n = n - 2; x = y; }
return n - ((x << 1) >>> 31);
}
/**
* 返回指定 long 值的二进制补码表示形式中的 1 位的数量。
* 此功能有时被称为填充计算。
* @param i
* @return int
*/
public static int bitCount(long i) {
// 每两位一组统计看有多少个1
// 0x55555555也就是01010101010101010101010101010101
i = i - ((i >>> 1) & 0x5555555555555555L);
// 每四位一组统计看有多少个1
// 0x33333333也就是110011001100110011001100110011
i = (i & 0x3333333333333333L) + ((i >>> 2) & 0x3333333333333333L);
// 每八位的1的个数
// 0x0f0f0f0f也就是00001111000011110000111100001111
i = (i + (i >>> 4)) & 0x0f0f0f0f0f0f0f0fL;
// 每16位
i = i + (i >>> 8);
// 每32位
i = i + (i >>> 16);
// 每64位
i = i + (i >>> 32);
// 最终与0x7f进行与运算,得到的结果,就是1的个数
return (int)i & 0x7f;
}
/**
* 返回根据指定的位数循环左移指定的 long 值的二进制补码表示形式而得到的值。
* (位是从左边(即高位)移出,从右边(即低位)再进入)
* 注意,使用负距离的左循环等同于右循环:
* rotateLeft(val, -distance) == rotateRight(val, distance)。
* 还要注意的是,以 32 的任何倍数进行的循环都是无操作指令,
* 因此,即使距离为负,除了最后五位外,
* 其余所有循环距离都可以忽略:
* rotateLeft(val, distance) == rotateLeft(val, distance & 0x1F)。
* @param i
* @param distance
* @return long
*/
public static long rotateLeft(long i, int distance) {
return (i << distance) | (i >>> -distance);
}
/**
* 返回根据指定的位数循环右移指定的 long 值的二进制补码表示形式而得到的值。
* (位是从右边(即低位)移出,从左边(即高位)再进入)
* 注意,使用负距离的右循环等同于左循环:
* rotateRight(val, -distance) == rotateLeft(val, distance)。
* 还要注意的是,以 32 的任何倍数进行的循环都是无操作指令,
* 因此,即使距离为负,除了最后五位外,
* 其余所有循环距离都可以忽略:
* rotateRight(val, distance) == rotateRight(val, distance & 0x1F)。
* @param i
* @param distance
* @return long
*/
public static long rotateRight(long i, int distance) {
return (i >>> distance) | (i << -distance);
}
/**
* 对i进行反转,反转也就是第1位和第64位对调,第2位和第63位对调等
* @param i
* @return int
*/
public static long reverse(long i) {
// 将相邻两位进行对调
i = (i & 0x5555555555555555L) << 1 | (i >>> 1) & 0x5555555555555555L;
// 将相邻四位进行对调
i = (i & 0x3333333333333333L) << 2 | (i >>> 2) & 0x3333333333333333L;
// 将相邻的八位进行对调
i = (i & 0x0f0f0f0f0f0f0f0fL) << 4 | (i >>> 4) & 0x0f0f0f0f0f0f0f0fL;
// 将相邻的十六位进行对调
i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL;
// 64位中的中间32对调,最高十六位和最低十六位对调
i = (i << 48) | ((i & 0xffff0000L) << 16) |
((i >>> 16) & 0xffff0000L) | (i >>> 48);
return i;
}
/**
* 返回指定 long 值的符号函数。(如果指定值为负,则返回 -1;
* 如果指定值为零,则返回 0;如果指定的值为正,则返回 1。)
* @param i
* @return int
*/
public static int signum(long i) {
// HD, Section 2-7
return (int) ((i >> 63) | (-i >>> 63));
}
/**
* 返回通过反转指定 long 值的二进制补码表示形式中字节的顺序而获得的值
* @param i
* @return long
*/
public static long reverseBytes(long i) {
i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL;
return (i << 48) | ((i & 0xffff0000L) << 16) |
((i >>> 16) & 0xffff0000L) | (i >>> 48);
}
// 序列号
private static final long serialVersionUID = 4290774380558885855L;
}
参考:JDK 1.6 API