The Integer class java source code Detailed

The Integer class java source code Detailed

Class definition

public final class Integer extends Number implements Comparable<Integer> {
    @Native public static final int   MIN_VALUE = 0x80000000;

    @Native public static final int   MAX_VALUE = 0x7fffffff;

    @SuppressWarnings("unchecked")
    public static final Class<Integer>  TYPE = (Class<Integer>) Class.getPrimitiveClass("int");

    final static char[] digits = {
        '0' , '1' , '2' , '3' , '4' , '5' ,
        '6' , '7' , '8' , '9' , 'a' , 'b' ,
        'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
        'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
        'o' , 'p' , 'q' , 'r' , 's' , 't' ,
        'u' , 'v' , 'w' , 'x' , 'y' , 'z'
    };

    public String toString() {
        return toString(value);
    }

    public static String toString(int i) {
        if (i == Integer.MIN_VALUE)
            return "-2147483648";
        int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
        char[] buf = new char[size];
        getChars(i, size, buf);
        return new String(buf, true);
    }

    public static String toString(int i, int radix) {
        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
            radix = 10;

        /* Use the faster version */
        if (radix == 10) {
            return toString(i);
        }

        char buf[] = new char[33];
        boolean negative = (i < 0);
        int charPos = 32;

        if (!negative) {
            i = -i;
        }

        while (i <= -radix) {
            buf[charPos--] = digits[-(i % radix)];
            i = i / radix;
        }
        buf[charPos] = digits[-i];

        if (negative) {
            buf[--charPos] = '-';
        }

        return new String(buf, charPos, (33 - charPos));
    }

    static void getChars(int i, int index, char[] buf) {
        int q, r;
        int charPos = index;
        char sign = 0;

        if (i < 0) {
            sign = '-';
            i = -i;
        }

        // Generate two digits per iteration
        while (i >= 65536) {
            q = i / 100;
        // really: r = i - (q * 100);
            r = i - ((q << 6) + (q << 5) + (q << 2));
            i = q;
            buf [--charPos] = DigitOnes[r];
            buf [--charPos] = DigitTens[r];
        }

        // Fall thru to fast mode for smaller numbers
        // assert(i <= 65536, i);
        for (;;) {
            q = (i * 52429) >>> (16+3);
            r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
            buf [--charPos] = digits [r];
            i = q;
            if (i == 0) break;
        }
        if (sign != 0) {
            buf [--charPos] = sign;
        }
    }

    final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                      99999999, 999999999, Integer.MAX_VALUE };

    // Requires positive x
    static int stringSize(int x) {
        for (int i=0; ; i++)
            if (x <= sizeTable[i])
                return i+1;
    }

    public static String toUnsignedString(int i, int radix) {
        return Long.toUnsignedString(toUnsignedLong(i), radix);
    }

    public static String toHexString(int i) {
        return toUnsignedString0(i, 4);
    }

    public static String toOctalString(int i) {
        return toUnsignedString0(i, 3);
    }

    public static String toBinaryString(int i) {
        return toUnsignedString0(i, 1);
    }

    private static String toUnsignedString0(int val, int shift) {
        // assert shift > 0 && shift <=5 : "Illegal shift value";
        int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
        int chars = Math.max(((mag + (shift - 1)) / shift), 1);
        char[] buf = new char[chars];

        formatUnsignedInt(val, shift, buf, 0, chars);

        // Use special constructor which takes over "buf".
        return new String(buf, true);
    }

     static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
        int charPos = len;
        int radix = 1 << shift;
        int mask = radix - 1;
        do {
            buf[offset + --charPos] = Integer.digits[val & mask];
            val >>>= shift;
        } while (val != 0 && charPos > 0);

        return charPos;
    }
}

nteger is a constant class with a final declaration, any class can not be inherited. Number and Integer class inherits class and implements the Comparable interface. Number class is an abstract class, 8 of the basic data types in addition to packaging Character and Boolean not inherited class, the rest are inherited Number class, the class for a method of converting various types of data, the interface to the Comparable a compareTo method, comparison between the size of the element is used.

  int type is Java occupying four bytes, which may represent the size range is -231--231-1 i.e. -2147483648--2147483647, we must not exceed the range of values ​​represented by at int.

    toString three method overloading, it can return a string represented by the integer data, which last method toString (int, int) the second parameter is a number represented in hexadecimal format.

 Internal (int) method is called stringsize toString () and getChars () method, stringsize () which is the number of bits used to calculate the parameter i is converted into the string after the string length, it has initialized a good internal bond int type array sizeTable to complete the calculation.

  Realized in the form of very clever. Note the negative sign bit comprising, a negative number of bits or so is stringSize (-i) + 1.

       getChars(int i,int index,char[] buf)

     i: number is initialized,

  index: this figure the length (including the negative sign "-")

  buf: a string container - a char array.

  If the first determination, if i <0, sign a note of its symbol "-", at the same time converted into an integer i. All of the following operations it only for integer, and finally [--charPos] = sign judge sign if the sign is not equal to zero the value of your first place buf char array ;.  

    private final int value;

    public Integer(int value) {
        this.value = value;
    }

    public Integer(String s) throws NumberFormatException {
        this.value = parseInt(s, 10);
    }

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

    public byte byteValue() {
        return (byte)value;
    }

    public short shortValue() {
        return (short)value;
    }

    public int intValue() {
        return value;
    }

    public long longValue() {
        return (long)value;
    }

    public float floatValue() {
        return (float)value;
    }

    public double doubleValue() {
        return (double)value;
    }

    public static int parseInt(String s) throws NumberFormatException {
        return parseInt(s,10);
    }

 public static int parseInt(String s, int radix) throws NumberFormatException{
     //如果转换的字符串如果为null,直接抛出空指针异常
     if (s == null) {
          throw new NumberFormatException("null");
     }
     //如果转换的radix(默认是10)<2 则抛出数字格式异常,因为进制最小是 2 进制
     if (radix < Character.MIN_RADIX) {
        throw new NumberFormatException("radix " + radix +
                                         " less than Character.MIN_RADIX");
     }
     //如果转换的radix(默认是10)>36 则抛出数字格式异常,因为0到9一共10位,a到z一共26位,所以一共36位
     //也就是最高只能有36进制数
     if (radix > Character.MAX_RADIX) {
         throw new NumberFormatException("radix " + radix +
                                         " greater than Character.MAX_RADIX");
     }
     int result = 0;
     boolean negative = false;
     int i = 0, len = s.length();//len是待转换字符串的长度
     int limit = -Integer.MAX_VALUE;//limit = -2147483647
     int multmin;
     int digit;
     //如果待转换字符串长度大于 0 
     if (len > 0) {
         char firstChar = s.charAt(0);//获取待转换字符串的第一个字符
         //这里主要用来判断第一个字符是"+"或者"-",因为这两个字符的 ASCII码都小于字符'0'
         if (firstChar < '0') {  
             if (firstChar == '-') {//如果第一个字符是'-'
                 negative = true;
                 limit = Integer.MIN_VALUE;
             } else if (firstChar != '+')//如果第一个字符是不是 '+',直接抛出异常
                 throw NumberFormatException.forInputString(s);
 
             if (len == 1) //待转换字符长度是1,不能是单独的"+"或者"-",否则抛出异常 
                 throw NumberFormatException.forInputString(s);
             i++;
         }
         multmin = limit / radix;
         //通过不断循环,将字符串除掉第一个字符之后,根据进制不断相乘在相加得到一个正整数
         //比如 parseInt("2abc",16) = 2*16的3次方+10*16的2次方+11*16+12*1 
         //parseInt("123",10) = 1*10的2次方+2*10+3*1 
         while (i < len) {
             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 {//如果待转换字符串长度小于等于0,直接抛出异常
         throw NumberFormatException.forInputString(s);
     }
     //根据第一个字符得到的正负号,在结果前面加上符号
     return negative ? result : -result;
 }

Constructor Integer (String) String to convert data that we enter into integer data.

First of all we need to know can be converted into a string of integer must be divided into two parts: the first one must be "+" or "-" and the remaining characters must be 0-9 and az

parseInt (String s) can convert the front toString (int i) integer data type into an output string, where the output is converted into an integer by parseInt (String s) can string.

Automatic packing and unpacking

  Automatic and automatic packing unpacking after JDK1.5 is the only function that is one among many java syntactic sugar, it is executed at compile time, based on the syntax of the code, when generated class file, decide whether unpacking and packing operation.

  ①, autoboxing

  We know that in general create a new class of objects needed by keyword, such as:

Object obj = new Object();

  But in fact, for the Integer class, but we can use this directly:

Integer a = 128;

  Why can this way, by decompiling tool, we can see that the generated class file is:

Integer a = Integer.valueOf(128);

  In fact, the object is () produced by the last new Integer return, but to note here the front section of the code, if the value of i -128 <= i <= 127 returns the cache object class, and create a new one does not the object, which we should pay attention to when comparing by equals.

  This is the basic data type of automatic packing, 128 is the basic data type, then parsed into the Integer class.

  ②, auto-unboxing

  Integer data will be assigned to the class represents the basic data type int, on the implementation of the automatic unpacking.

 Integer a = new Integer(128);
 int m = a;

  Decompile generated class file:

 Integer a = new Integer(128);
 int m = a.intValue();

  Briefly: autoboxing is Integer.valueOf (int i); automatic unpacking is i.intValue ();

About cache class

public static void main(String[] args) {
    Integer i = 10;
    Integer j = 10;
    System.out.println(i == j);
      
    Integer a = 128;
    Integer b = 128;
    System.out.println(a == b);
     
    int k = 10;
    System.out.println(k == i);
    int kk = 128;
    System.out.println(kk == a);
      
    Integer m = new Integer(10);
    Integer n = new Integer(10);
    System.out.println(m == n);
}

 the answer is:

  

 ①, Integer is a wrapper class int, int is one of the eight basic types of data (byte, char, short, int, long, float, double, boolean)

 ②, Integer is a class, the default value is null, int is the basic data type, the default value is 0;

 ③, Integer is represented by an object with a reference point to the object, and int is the basic data type, the value is stored directly.

 First, direct statement Integer i = 10, automatically packing becomes Integer i = Integer.valueOf (10); Integer i is automatically unpacking i.intValue ().

  ①, the first print to true

  For i == j, we know that these are two Integer class, they are more use should be equals, here is the comparison with == address, then the result is definitely false, but the result is actually true.

  In the analysis we can know the source i> = -128 and i <= 127, when the first value of i by statement placed in the cache, the cache and direct access to the second data, instead of re-creating a target Ingeter . Then the first print result as i = 10 in the buffer indicates a range, it is true.

  ②, the second print result is false

  From the above analysis we know that 128 is not, so the first time to create the object is not cached between -128 to 127, the second creates a new Integer object. Therefore, the print result is false

  ③, the third print result is true

  Integer automatic unpacking function, i.e. compare two basic types of data, the result is true, of course

  ④, fourth print result is true

  Interpretation and third the same. int and integer (regardless of whether new) ratio, are true, because Integer will automatically go unboxing to int compare.

  ⑤, the fifth print result is false

  Because of this though it is 10, but the two objects we are creating through the new keyword, the concept is not present in the cache. Compares two objects created with the new keyword with ==, the result of course is false.

Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
 
Integer e = 321;
Integer f = 321;
 
Long g = 3L;
Long h = 2L;
 
System.out.println(c == d);
System.out.println(e == f);
System.out.println(c == (a + b));
System.out.println(c.equals((a+b)));
System.out.println(g == (a+b));
System.out.println(g.equals(a+b));
System.out.println(g.equals(a+h));

 Decompile results:

  Print results:

true
false
true
true
true
false
true

  Analysis: first and second result little doubt, Integer class cache problem of -128 to 127;

  Since the third a + b contains arithmetic, and therefore triggers an automatic unpacking procedure (intValue method calls), comparison operators == automatic unpacking of the left turn, they are compared values ​​are equal.

  After the fourth to c.equals (a + b) will be fired automatically unpacking process, and then trigger the automatic packing process, i.e. a + b, each call will first intValue method, the value obtained after the addition operation, Integer.valueOf method is invoked, then equals comparisons.

  For the fifth after g == (a + b), first calculates a + b, is a respective first call intValue method, the value obtained, since g is in front of the Long type, is automatically unpacking long, == operators can convert the implicit data type small range for a wide range of data types, that is, it will be converted to long int type, two types of long compared values.

  For the sixth g.equals (a + b), Similarly a + b will first automatically unpacking and packing the results automatically, it is noted that  equals operator does not carry out conversion. So is Long.equals (Integer), the result of course is false

  For the seventh g.equals (a + h), the operator will + type conversion, a + h after each int + unboxing is long, the result is long, and long for the automatic packing Long, Long for two equals judgment.

    @Override
    public int hashCode() {
        return Integer.hashCode(value);
    }

    public static int hashCode(int value) {
        return value;
    }

    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

    public static Integer getInteger(String nm) {
        return getInteger(nm, null);
    }

    public static Integer getInteger(String nm, int val) {
        Integer result = getInteger(nm, null);
        return (result == null) ? Integer.valueOf(val) : result;
    }

    public static Integer getInteger(String nm, Integer val) {
        String v = null;
        try {
            v = System.getProperty(nm);
        } catch (IllegalArgumentException | NullPointerException e) {
        }
        if (v != null) {
            try {
                return Integer.decode(v);
            } catch (NumberFormatException e) {
            }
        }
        return val;
    }

    public static Integer decode(String nm) throws NumberFormatException {
        int radix = 10;
        int index = 0;
        boolean negative = false;
        Integer 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 = Integer.valueOf(nm.substring(index), radix);
            result = negative ? Integer.valueOf(-result.intValue()) : result;
        } catch (NumberFormatException e) {
            // If number is Integer.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 = Integer.valueOf(constant, radix);
        }
        return result;
    }

    public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }

    public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }

    public static int compareUnsigned(int x, int y) {
        return compare(x + MIN_VALUE, y + MIN_VALUE);
    }

    public static long toUnsignedLong(int x) {
        return ((long) x) & 0xffffffffL;
    }

    public static int divideUnsigned(int dividend, int divisor) {
        // In lieu of tricky code, for now just use long arithmetic.
        return (int)(toUnsignedLong(dividend) / toUnsignedLong(divisor));
    }

    public static int remainderUnsigned(int dividend, int divisor) {
        // In lieu of tricky code, for now just use long arithmetic.
        return (int)(toUnsignedLong(dividend) % toUnsignedLong(divisor));
    }


    // Bit twiddling
    @Native public static final int SIZE = 32;

    public static final int BYTES = SIZE / Byte.SIZE;

    public static int highestOneBit(int i) {
        // HD, Figure 3-1
        i |= (i >>  1);
        i |= (i >>  2);
        i |= (i >>  4);
        i |= (i >>  8);
        i |= (i >> 16);
        return i - (i >>> 1);
    }

    public static int lowestOneBit(int i) {
        // HD, Section 2-1
        return i & -i;
    }

    public static int numberOfLeadingZeros(int i) {
        // HD, Figure 5-6
        if (i == 0)
            return 32;
        int n = 1;
        if (i >>> 16 == 0) { n += 16; i <<= 16; }
        if (i >>> 24 == 0) { n +=  8; i <<=  8; }
        if (i >>> 28 == 0) { n +=  4; i <<=  4; }
        if (i >>> 30 == 0) { n +=  2; i <<=  2; }
        n -= i >>> 31;
        return n;
    }

    public static int numberOfTrailingZeros(int i) {
        // HD, Figure 5-14
        int y;
        if (i == 0) return 32;
        int n = 31;
        y = i <<16; if (y != 0) { n = n -16; i = y; }
        y = i << 8; if (y != 0) { n = n - 8; i = y; }
        y = i << 4; if (y != 0) { n = n - 4; i = y; }
        y = i << 2; if (y != 0) { n = n - 2; i = y; }
        return n - ((i << 1) >>> 31);
    }

    public static int bitCount(int i) {
        // HD, Figure 5-2
        i = i - ((i >>> 1) & 0x55555555);
        i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
        i = (i + (i >>> 4)) & 0x0f0f0f0f;
        i = i + (i >>> 8);
        i = i + (i >>> 16);
        return i & 0x3f;
    }

    public static int rotateLeft(int i, int distance) {
        return (i << distance) | (i >>> -distance);
    }

    public static int rotateRight(int i, int distance) {
        return (i >>> distance) | (i << -distance);
    }

    public static int reverse(int i) {
        // HD, Figure 7-1
        i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
        i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
        i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
        i = (i << 24) | ((i & 0xff00) << 8) |
            ((i >>> 8) & 0xff00) | (i >>> 24);
        return i;
    }

    public static int signum(int i) {
        // HD, Section 2-7
        return (i >> 31) | (-i >>> 31);
    }

    public static int reverseBytes(int i) {
        return ((i >>> 24)           ) |
               ((i >>   8) &   0xFF00) |
               ((i <<   8) & 0xFF0000) |
               ((i << 24));
    }

    public static int sum(int a, int b) {
        return a + b;
    }

    public static int max(int a, int b) {
        return Math.max(a, b);
    }

    public static int min(int a, int b) {
        return Math.min(a, b);
    }

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    @Native private static final long serialVersionUID = 1360826667806852920L;
}

equals (Object obj) method, this method is very simple, first determine the relationship between two objects by comparing instanceof keyword, then the object into strong Integer, by an automatic unpacking, data is converted into two basic classes int, then == comparison.

hashCode (), hashCode method of the Integer class is relatively simple, direct return its data type int.

compareTo(int x,int y)

 If x <y -1

 Return 0 if x == y

 If x> y returns 1

 System.out.println(Integer.compare(1, 2));//-1
 System.out.println(Integer.compare(1, 1));//0
 System.out.println(Integer.compare(1, 0));//1

  So basically the main method of class Integer introduce so much, if there are more important behind, it will no longer be updated.

 

Published 370 original articles · won praise 88 · views 290 000 +

Guess you like

Origin blog.csdn.net/qq_35029061/article/details/100469379