美文网首页探索JDK
探索JDK之Long类

探索JDK之Long类

作者: 苏小小北 | 来源:发表于2018-10-29 20:20 被阅读0次

    1. 简介

    Long类封装了一个值long原始类型的一个对象。一个Long类型的对象包含一个字段的类型是long。此外,该类提供了一些方法处理long、String的相关的操作。

    2. 源码


    Long类中属性有:

    • 实例变量
    • 实例方法
    • 类变量
    • 类方法
    • 静态内部类
    • 构造器
    (1) 实例变量:
    1. value:表示数值大小(final不可变)
        private final long value;
    
    (2) 实例方法:
    1. byteValue:返回截断的byte类型值
        public byte byteValue() {
            return (byte)value;
        }
    
    1. shortValue:返回截断的short类型值
        public short shortValue() {
            return (short)value;
        }
    
    1. intValue:返回int类型值
        public int intValue() {
            return value;
        }
    
    1. longValue:返回long类型值
        public long longValue() {
            return (long)value;
        }
    
    1. floatValue:返回float类型值
        public float floatValue() {
            return (float)value;
        }
    
    1. doubleValue:返回double类型值
        public double doubleValue() {
            return (double)value;
        }
    
    1. toString: 重写Object类的toString方法,这里调用了类方法toString,后面解释
        public String toString() {
            return toString(value);
        }
    
    1. hashCode:返回hash值,调用静态方法hashCode,详解见类方法hashCode
        @Override
        public int hashCode() {
            return Long.hashCode(value);
        }
    
    1. equals:与其他对象比较大小(可以跟任何对象比较)
        public boolean equals(Object obj) {
            if (obj instanceof Long) {
                return value == ((Long)obj).longValue();
            }
            return false;
        }
    
    1. compareTo:与另一Long比较大小,返回-1,0,1
        public int compareTo(Long anotherLong) {
            return compare(this.value, anotherLong.value);
        }
    
    (3) 类变量:
    1. MIN_VALUE:Long最小值,为0x8000000000000000L
        public static final int   MIN_VALUE = 0x8000000000000000L;
    
    1. MAX_VALUE:Long最大值,为0x7fffffffffffffffL
        public static final long MAX_VALUE = 0x7fffffffffffffffL;
    
    1. TYPE:对应的原始类的类型"long"
        public static final Class<Long>     TYPE = (Class<Long>) Class.getPrimitiveClass("long");
    
    1. SIZE:Long数值二进制占用bit数目,为64
        public static final int SIZE = 64;
    

    4.Bytes:Long数值二进制占用byte数目,为8

        public static final int BYTES = SIZE / Byte.SIZE;
    
    1. serialVersionUID:序列版本号
        private static final long serialVersionUID = 1360826667806852920L;
    
    (4) 类方法:
    1. toString(long i):返回数值为i的字符串,基数为10
        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];
            getChars(i, size, buf);
            return new String(buf, true);
        }
            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;
            }
    
            // Get 2 digits/iteration using longs until quotient fits into an int
            while (i > Integer.MAX_VALUE) {
                q = i / 100;
                // really: r = i - (q * 100);
                r = (int)(i - ((q << 6) + (q << 5) + (q << 2)));
                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 >= 65536) {
                q2 = i2 / 100;
                // really: r = i2 - (q * 100);
                r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2));
                i2 = q2;
                buf[--charPos] = Integer.DigitOnes[r];
                buf[--charPos] = Integer.DigitTens[r];
            }
    
            // Fall thru to fast mode for smaller numbers
            // assert(i2 <= 65536, i2);
            for (;;) {
                q2 = (i2 * 52429) >>> (16+3);
                r = i2 - ((q2 << 3) + (q2 << 1));  // r = i2-(q2*10) ...
                buf[--charPos] = Integer.digits[r];
                i2 = q2;
                if (i2 == 0) break;
            }
            if (sign != 0) {
                buf[--charPos] = sign;
            }
        }
    

    3.String toString(long i, int radix):转换为String,基数为radix
    Integer中有toUnsignedString0(int val, int shift)方法,思路类似

        public static String toString(long i, int radix) {
            if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
                radix = 10;
            if (radix == 10)
                return toString(i);
            char[] buf = new char[65];
            int charPos = 64;
            boolean negative = (i < 0);
    
            if (!negative) {
                i = -i;
            }
    
            while (i <= -radix) {
                buf[charPos--] = Integer.digits[(int)(-(i % radix))];
                i = i / radix;
            }
            buf[charPos] = Integer.digits[(int)(-i)];
    
            if (negative) {
                buf[--charPos] = '-';
            }
    
            return new String(buf, charPos, (65 - charPos));
        }
    
    1. toUnsignedString0(long val, int shift):将integer转换为无符号数的字符串形式
      与Integer.toUnsignedString0(int val, int shift)类似
           static String toUnsignedString0(long val, int shift) {
            // assert shift > 0 && shift <=5 : "Illegal shift value";
            int mag = Long.SIZE - Long.numberOfLeadingZeros(val);
            int chars = Math.max(((mag + (shift - 1)) / shift), 1);
            char[] buf = new char[chars];
    
            formatUnsignedLong(val, shift, buf, 0, chars);
            return new String(buf, true);
        }
    
    1. toBinaryString(long i):转换为二进制形式(补码)
      看懂3中的toUnsignedString0方法,这个应该就比较简单
        // 直接调用toUnsingedString0方法,radix为2,所以shift为1
        public static String toBinaryString(long i) {
            return toUnsignedString0(i, 1);
        }
    
    1. toOctalString(longi):转换为八进制形式(补码)
      看懂3中的toUnsignedString0方法,这个应该就比较简单
        // 直接调用toUnsignedString0方法,radix为8, 所以shift为3
        public static String toOctalString(long i) {
            return toUnsignedString0(i, 3);
        }
    
    1. toHexString(long i):转换为十六进制形式(补码)
      看懂3中的toUnsignedString0方法,这个应该就比较简单
        // 直接调用toUnsignedString0方法,radix为16, 所以shift为4
        public static String toHexString(long i) {
            return toUnsignedString0(i, 4);
        }
    
    1. toUnsignedBigInteger(long i):将i作为无符号long类型转换为BigInteger
           private static BigInteger toUnsignedBigInteger(long i) {
            if (i >= 0L)
                return BigInteger.valueOf(i);
            else {
                int upper = (int) (i >>> 32);
                int lower = (int) i;
    
                // return (upper << 32) + lower
                return (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32).
                    add(BigInteger.valueOf(Integer.toUnsignedLong(lower)));
            }
        }
    
    1. toUnsignedString(long i):转换为long无符号字符串
        public static String toString(long i, int radix) {
            if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
                radix = 10;
            if (radix == 10)
                return toString(i);
            char[] buf = new char[65];
            int charPos = 64;
            boolean negative = (i < 0);
    
            if (!negative) {
                i = -i;
            }
    
            while (i <= -radix) {
                buf[charPos--] = Integer.digits[(int)(-(i % radix))];
                i = i / radix;
            }
            buf[charPos] = Integer.digits[(int)(-i)];
    
            if (negative) {
                buf[--charPos] = '-';
            }
    
            return new String(buf, charPos, (65 - charPos));
        }
        public static String toUnsignedString(long i, int radix) {
            if (i >= 0)
                return toString(i, radix);
            else {
                switch (radix) {
                case 2:
                    return toBinaryString(i);
    
                case 4:
                    return toUnsignedString0(i, 2);
    
                case 8:
                    return toOctalString(i);
    
                case 10:
                    /*
                     * We can get the effect of an unsigned division by 10
                     * on a long value by first shifting right, yielding a
                     * positive value, and then dividing by 5.  This
                     * allows the last digit and preceding digits to be
                     * isolated more quickly than by an initial conversion
                     * to BigInteger.
                     */
                    long quot = (i >>> 1) / 5;
                    long rem = i - quot * 10;
                    return toString(quot) + rem;
    
                case 16:
                    return toHexString(i);
    
                case 32:
                    return toUnsignedString0(i, 5);
    
                default:
                    return toUnsignedBigInteger(i).toString(radix);
                }
            }
        }
    
    1. parseLong(String s, int radix):将String解析成long,基数为radix
      思路同Integer.parseInt(String s, int radix)
        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') { // Possible leading "+" or "-"
                    if (firstChar == '-') {
                        negative = true;
                        limit = Long.MIN_VALUE;
                    } else if (firstChar != '+')
                        throw NumberFormatException.forInputString(s);
    
                    if (len == 1) // Cannot have lone "+" or "-"
                        throw NumberFormatException.forInputString(s);
                    i++;
                }
                multmin = limit / radix;
                while (i < len) {
                    // Accumulating negatively avoids surprises near MAX_VALUE
                    digit = Character.digit(s.charAt(i++),radix);
                    if (digit < 0) {
                        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;
        }
    
    1. parseLong(String s):将String解析成long,基数为10
        // 直接调用9中的方法parseLong(s, 10)
        public static long parseLong(String s) throws NumberFormatException {
            return parseLong(s, 10);
        }
    
    1. parseUnsignedLong(String s, int radix):将无符号类型数值的String转换为long,基数为radix
      思路同Integer.parseUnsignedInt(String s, int radix)
        public static long parseUnsignedLong(String s, int radix)
                    throws NumberFormatException {
            if (s == null)  {
                throw new NumberFormatException("null");
            }
    
            int len = s.length();
            if (len > 0) {
                char firstChar = s.charAt(0);
                if (firstChar == '-') {
                    throw new
                        NumberFormatException(String.format("Illegal leading minus sign " +
                                                           "on unsigned string %s.", s));
                } else {
                    if (len <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits
                        (radix == 10 && len <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits
                        return parseLong(s, radix);
                    }
    
                    // No need for range checks on len due to testing above.
                    long first = parseLong(s.substring(0, len - 1), radix);
                    int second = Character.digit(s.charAt(len - 1), radix);
                    if (second < 0) {
                        throw new NumberFormatException("Bad digit at end of " + s);
                    }
                    long result = first * radix + second;
                    if (compareUnsigned(result, first) < 0) {
                        /*
                         * The maximum unsigned value, (2^64)-1, takes at
                         * most one more digit to represent than the
                         * maximum signed value, (2^63)-1.  Therefore,
                         * parsing (len - 1) digits will be appropriately
                         * in-range of the signed parsing.  In other
                         * words, if parsing (len -1) digits overflows
                         * signed parsing, parsing len digits will
                         * certainly overflow unsigned parsing.
                         *
                         * The compareUnsigned check above catches
                         * situations where an unsigned overflow occurs
                         * incorporating the contribution of the final
                         * digit.
                         */
                        throw new NumberFormatException(String.format("String value %s exceeds " +
                                                                      "range of unsigned long.", s));
                    }
                    return result;
                }
            } else {
                throw NumberFormatException.forInputString(s);
            }
        }
    
    1. parseUnsignedLong(String s): 将无符号类型数值的String转换为long,基数为10
        // 直接调用11中的parseUnsignedLong(String s, int radix)
        public static long parseUnsignedLong(String s) throws NumberFormatException {
            return parseUnsignedLong(s, 10);
        }
    
    1. valueOf(String s, int radix):同11中 parseInt(char ch, int radix)
        public static Long valueOf(String s, int radix) throws NumberFormatException {
            return Long.valueOf(parseLong(s, radix));
        }
    
    1. valueOf(String s):同12中 parseLong(char ch)
        public static Long valueOf(String s) throws NumberFormatException
        {
            return Long.valueOf(parseLong(s, 10));
        }
    
    1. valueOf(int i):根据int值返回Integer对象,如果在缓存池中,会返回缓存池中的对象,否则new对象,返回对象。缓存池默认是缓存 -128 ~ 127 的Interger对象,具体见静态内部类IntegerCache。
        public static Long valueOf(long l) {
            final int offset = 128;
            if (l >= -128 && l <= 127) { // will cache
                return LongCache.cache[(int)l + offset];
            }
            return new Long(l);
        }
    
    1. hashCode():重写hashCode,hash值,利用异或运算返回新的hashCode
        public static int hashCode(long value) {
            return (int)(value ^ (value >>> 32));
        }
    
    1. decode(String nm):解析字符串为Long,基数自动从字符串解析, 用于解析系统属性参数
        public static Long decode(String nm) throws NumberFormatException {
            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);
            // Handle sign, if present
            if (firstChar == '-') {
                negative = true;
                index++;
            } else if (firstChar == '+')
                index++;
    
            // Handle radix specifier, if present
            if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
                index += 2;
                radix = 16;
            }
            else if (nm.startsWith("#", index)) {
                index ++;
                radix = 16;
            }
            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);
                result = negative ? Long.valueOf(-result.longValue()) : result;
            } catch (NumberFormatException e) {
                // If number is Long.MIN_VALUE, we'll end up here. The next line
                // handles this case, and causes any genuine format error to be
                // rethrown.
                String constant = negative ? ("-" + nm.substring(index))
                                           : nm.substring(index);
                result = Long.valueOf(constant, radix);
            }
            return result;
        }
    
    1. getLong(String nm, Integer val):从系统属性解析读取指定key的属性值v,失败返回默认val对象
        public static Long getLong(String nm, Long val) {
            String v = null;
            try {
                v = System.getProperty(nm);
            } catch (IllegalArgumentException | NullPointerException e) {
            }
            if (v != null) {
                try {
                    return Long.decode(v);
                } catch (NumberFormatException e) {
                }
            }
            return val;
        }
    
    1. 从系统属性解析读取指定key的属性值v,失败返回默认值为val的Integer
        public static Long getLong(String nm, long val) {
            Long result = Long.getLong(nm, null);
            return (result == null) ? Long.valueOf(val) : result;
        }
    
    1. compare(long x, long y):比较大小,返回值-1,0,1
        public static int compare(long x, long y) {
            return (x < y) ? -1 : ((x == y) ? 0 : 1);
        }
    
    1. compareUnsigned(long x, long y):比较无符号int的值大小
        // 如果x,y 均为正数,谁值大,对应的无符号值也大
        // 如果x,y 均为负数,谁值更小,加上MIN_VALUE越界更多,所以值越大
        // 如果x,y 一正一负,负数+MIN_VALUE越界为正数,所以肯定负数大
        public static int compareUnsigned(long x, long y) {
            return compare(x + MIN_VALUE, y + MIN_VALUE);
        }
    
    1. divideUnsigned(int dividend, int divisor) :无符号int数值相除
        public static long divideUnsigned(long dividend, long divisor) {
            if (divisor < 0L) { // signed comparison
                // Answer must be 0 or 1 depending on relative magnitude
                // of dividend and divisor.
                return (compareUnsigned(dividend, divisor)) < 0 ? 0L :1L;
            }
    
            if (dividend > 0) //  Both inputs non-negative
                return dividend/divisor;
            else {
                /*
                 * For simple code, leveraging BigInteger.  Longer and faster
                 * code written directly in terms of operations on longs is
                 * possible; see "Hacker's Delight" for divide and remainder
                 * algorithms.
                 */
                return toUnsignedBigInteger(dividend).
                    divide(toUnsignedBigInteger(divisor)).longValue();
            }
        }
    
    1. divideUnsigned(long dividend, long divisor):无符号除法
        public static long divideUnsigned(long dividend, long divisor) {
            if (divisor < 0L) { // signed comparison
                // Answer must be 0 or 1 depending on relative magnitude
                // of dividend and divisor.
                return (compareUnsigned(dividend, divisor)) < 0 ? 0L :1L;
            }
    
            if (dividend > 0) //  Both inputs non-negative
                return dividend/divisor;
            else {
                /*
                 * For simple code, leveraging BigInteger.  Longer and faster
                 * code written directly in terms of operations on longs is
                 * possible; see "Hacker's Delight" for divide and remainder
                 * algorithms.
                 */
                return toUnsignedBigInteger(dividend).
                    divide(toUnsignedBigInteger(divisor)).longValue();
            }
        }
    
    1. remainderUnsigned(long dividend, long divisor):无符号long数值取余
        public static long remainderUnsigned(long dividend, long divisor) {
            if (dividend > 0 && divisor > 0) { // signed comparisons
                return dividend % divisor;
            } else {
                if (compareUnsigned(dividend, divisor) < 0) // Avoid explicit check for 0 divisor
                    return dividend;
                else
                    return toUnsignedBigInteger(dividend).
                        remainder(toUnsignedBigInteger(divisor)).longValue();
            }
        }
    
    1. highestOneBit(long i):取数值对应二进制的最高位第一个1,然后其他位全设为0,返回这个值
      同Integer.highestOneBit(int i)
        public static long highestOneBit(long i) {
            // HD, Figure 3-1
            i |= (i >>  1);
            i |= (i >>  2);
            i |= (i >>  4);
            i |= (i >>  8);
            i |= (i >> 16);
            i |= (i >> 32);
            return i - (i >>> 1);
        }
    
    1. lowestOneBit(long i):取数值对应二进制的最低位第一个1,然后其他全设为0,返回这个值
      同Integer.lowestOneBit(int i)
        public static long lowestOneBit(long i) {
            // HD, Section 2-1
            return i & -i;
        }
    
    1. numberOfLeadingZeros(long i):补码对应前缀连续0的个数
      同Integer.numberOfLeadingZeros(int i)
      // 前缀0的个数,也就是找到最高位1的位置
      // 通常我们获取最高位1用 去一位一位的找 的方法去做,这样遍历32次才可以
      // 这里运用了二分的方式去搜索,log(N)内完成
        public static int numberOfLeadingZeros(long i) {
            // HD, Figure 5-6
             if (i == 0)
                return 64;
            int n = 1;
            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;
        }
    
    1. numberOfTrailingZeros(long i):补码对应后缀连续0的个
      同25中 numberOfLeadingZeros(long i)的前缀连续0的个数求法
        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);
        }
    
    1. bitCount(long i):计算二进制中1的个数
      (同Integer.bitCount(int i))
      这是比较巧妙一种方式,详解见https://www.jianshu.com/p/0d0439dc7c6d
         public static int bitCount(long i) {
            // HD, Figure 5-14
            i = i - ((i >>> 1) & 0x5555555555555555L);
            i = (i & 0x3333333333333333L) + ((i >>> 2) & 0x3333333333333333L);
            i = (i + (i >>> 4)) & 0x0f0f0f0f0f0f0f0fL;
            i = i + (i >>> 8);
            i = i + (i >>> 16);
            i = i + (i >>> 32);
            return (int)i & 0x7f;
         }
    
    1. rotateLeft(long i, int distance):二进制按位左旋转
        public static long rotateLeft(long i, int distance) {
            return (i << distance) | (i >>> -distance);
        }
    
    1. rotateRight(long i, int distance):二进制按位右旋转
        public static long rotateRight(long i, int distance) {
            return (i >>> distance) | (i << -distance);
        }
    
    1. reverse(long i):二进制按位反转
      (同Integer.reverse(int))
      非常巧妙一种方式,详解见https://www.jianshu.com/u/0e206eac3b5c
        public static long reverse(long i) {
            // HD, Figure 7-1
            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;
            i = (i << 48) | ((i & 0xffff0000L) << 16) |
                ((i >>> 16) & 0xffff0000L) | (i >>> 48);
            return i;
        }
    
    1. signum(int i):正负号函数
        public static int signum(int i) {
            // HD, Section 2-7
            return (i >> 31) | (-i >>> 31);
        }
    
    1. reverseBytes(long i):按字节反转
        public static int signum(long i) {
            // HD, Section 2-7
            return (int) ((i >> 63) | (-i >>> 63));
        }
    
    (5) 构造器:
    1. Long(long value):按long 构造
        public Long(long value) {
            this.value = value;
        }
    
    1. Long(String s):按String构造
        public Long(String s) throws NumberFormatException {
            this.value = parseLong(s, 10);
        }
    
    (6) 静态内部类:
    1. LongCache:Long缓存池
      缓存-128到127的数值的Long对象,初始化类就new好了缓存对象
            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);
            }
        }
    

    其他


    本人也是在慢慢学习中,如有错误还请原谅、敬请指出,谢谢!

    相关文章

      网友评论

        本文标题:探索JDK之Long类

        本文链接:https://www.haomeiwen.com/subject/heditqtx.html