Article related source:

Integer.java





The longer you develop, the more you realize the importance of the basics. Take a look at the JDK source code and fill in any gaps. After reading this, you will find that the JDK source code really surprises you.

Integer is a wrapper class for the basic int. It provides methods for handling int values, and for converting strings to and from ints. In addition, it provides some bit operations from Henry S. Warren Jr. Hacker’s Delight.

Class declaration

First look at the Integer class declaration:

public final class Integer extends Number implements Comparable<Integer>{}
Copy the code

Inetger is immutable and cannot be inherited. For a more detailed introduction to immutable classes, you can read my previous article “Why Are Strings immutable?” .

Integer inherits the abstract class Number and implements the following methods: ByteValue () shortValue() intValue() longValue() floatValue() doubleValue();

Integer also implements the Comparable interface and therefore also has the ability to compare object sizes, with the compareTo() method implemented as follows:

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);
}
Copy the code

field

private final int value; // The Integer class wraps a value that is really used to store an int value

public static final int   MIN_VALUE = 0x80000000; // int the minimum value is -2^31

public static final int   MAX_VALUE = 0x7fffffff; // int the maximum value is 2^31-1

public static final Class<Integer>  TYPE = (Class<Integer>) Class.getPrimitiveClass("int"); // The base type int is an instance of the wrapper class

public static final int SIZE = 32; // The number of bits required for an int in the form of a binary complement

public static final int BYTES = SIZE / Byte.SIZE; // The number of bytes required for an int in the form of a binary complement. 1.8 New Fields

private static final long serialVersionUID = 1360826667806852920L; / / the serialization
Copy the code

Integer has only one non-static field value that represents the int value it wraps. 0x80000000 and 0x7fffff are hexadecimal representations of the minimum and maximum values of int, respectively.

We all know that ints are 4 bytes and 32 bits, and unlike C/C++, the range of integers in Java is independent of the machine on which the Java code is running. Whether on a 16 – bit system, 32 – bit system, or 64 – bit system, int is always 4 bytes. This is also the “write once, run anywhere” aspect of Java.

The constructor

Integer has two constructors. The first one looks like this:

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

The primitive type value is passed directly and assigned to the value field. Take a look at the second constructor:

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

The argument is a String, converted to int by parseInt(String S,int radix), and assigned to the value field.

String to int, it’s easy to understand a few examples:

“1234” – > 123

– > 5678-5678

“ff” -> 255

The Integer class enumerates all the characters that can be used to represent numbers, depending on the base:

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'
};
Copy the code

Let’s look at the implementation of the parseInt() function.

methods

parseInt(String,int) / parseInt(String)

public static int parseInt(String s) throws NumberFormatException {
    return parseInt(s,10);
}
Copy the code
public static int parseInt(String s, int radix)
            throws NumberFormatException
{
    /* * WARNING: This method may be invoked early during VM initialization * before IntegerCache is initialized. Care must be taken to not use * the valueOf method. */

    if (s == null) {
        throw new NumberFormatException("null");
    }

    if (radix < Character.MIN_RADIX) { // The minimum base value is 2
        throw new NumberFormatException("radix " + radix +
                                        " less than Character.MIN_RADIX");
    }

    if (radix > Character.MAX_RADIX) { // The maximum base is 36
        throw new NumberFormatException("radix " + radix +
                                        " greater than Character.MAX_RADIX");
    }

    int result = 0;
    boolean negative = false;
    int i = 0, len = s.length();
    int limit = -Integer.MAX_VALUE;
    int multmin;
    int digit;

    if (len > 0) {
        char firstChar = s.charAt(0);
        // '0' == 48, all non-numbers and letters below 48
        // '+' == 43, '-' == 45
        if (firstChar < '0') { // Possible leading "+" or "-"
            if (firstChar == The '-') {
                negative = true;
                limit = Integer.MIN_VALUE;
            } else if(firstChar ! ='+') // The first character is not a number or letter, nor is it + or -, and throws an exception
                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
            // Convert char to the corresponding base int
            digit = Character.digit(s.charAt(i++),radix);
            if (digit < 0) {
                throw NumberFormatException.forInputString(s);
            }
            /* * multmin = limit/radix, * if result > multmin, the radix will overflow */
            if (result < multmin) {
                throw NumberFormatException.forInputString(s);
            }
            result *= radix;
            ParseInt ("2147483648",10) does not pass this check
            // 2147483648 == Integer.MAX_VALUE + 1
            if (result < limit + digit) {
                throw NumberFormatException.forInputString(s);
            }
            result -= digit; // Use negative subtraction instead of positive summation to prevent overflow}}else {
        throw NumberFormatException.forInputString(s);
    }
    return negative ? result : -result;
}
Copy the code

The code is long, but the logic is simple. Take parseInt(“1234”,10) for example:

1 * 1234 = (((10) + 2) * 10 + 3) * 10 + 4Copy the code

It doesn’t actually add up like this, it adds up as a negative number. Because int has a maximum value of 2^31-1 and a minimum value of -2^31, positive summing may cause overflow. ParseInt () does two overflow checks and throws an exception if it overflows.

In addition, another point to note is the range of values in the base. The minimum base is 2 and the maximum base is 36. Exceptions outside this range are thrown directly. All possible digits for this range are stored in the static array digits:

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'
};
Copy the code

parseUnsignedInt(String,int) / parseUnsignedInt(String)

Ints are signed in Java, so parseInt() is also signed. Integer also provides the parseUnsignedInt function to handle unsigned types. After all, Java doesn’t have unsigned numbers at all, and using negative numbers for values greater than integer.max_value is an overflow.

public static int parseInt(String s) throws NumberFormatException {
    return parseInt(s,10);
}
Copy the code
public static int parseUnsignedInt(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 == The '-') { // Unsigned count - begins with an exception
            throw new
                NumberFormatException(String.format("Illegal leading minus sign " +
                                                   "on unsigned string %s.", s));
        } else {
            /* * Call parseInt() as a signed number * in other cases as long, call long.parselong () */
            if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
                (radix == 10 && len <= 9)) {// Integer.MAX_VALUE in base 10 is 10 digits
                return parseInt(s, radix);
            } else {
                long ell = Long.parseLong(s, radix);
                if ((ell & 0xffff_ffff_0000_0000L) = =0) { // Does not exceed the maximum value of unsigned int
                    return (int) ell;
                } else { If an unsigned int exceeds the maximum value, an exception is thrown
                    throw new
                        NumberFormatException(String.format("String value %s exceeds " +
                                                            "range of unsigned int.", s)); }}}}else {
        throwNumberFormatException.forInputString(s); }}Copy the code

A few things to note:

  • In order to-At the beginning, throw an exception directly
  • Make sure it is a signed type, still callparseInt(), otherwise regarded aslongTo deal with

After calling long.parselong () to get the return value, we need to determine if the maximum value of an unsigned int is exceeded. The judgment method used above is:

if ((ell & 0xffff_ffff_0000_0000L) = =0)
Copy the code

Satisfying this condition means that the height of ell must be 0, so it cannot exceed the maximum value of an unsigned int.

In addition to the parseInt() series, there are several String to int methods.

decode(String)

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 == The '-') { / / negative
        negative = true;
        index++;
    } else if (firstChar == '+') / / positive
        index++;

    // Handle radix specifier, if present
    // Start with "0x", "0x", "#" to indicate hexadecimal
    // Starting with "0" indicates octal
    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
        // resuppress.integer. MIN_VALUE will enter this branch
        String constant = negative ? ("-" + nm.substring(index))
                                   : nm.substring(index);
        result = Integer.valueOf(constant, radix);
    }
    return result;
}
Copy the code

Converts a particular string to an int value, which can accept decimal, hexadecimal, or octal strings. Strings starting with 0x, 0x, and # represent hexadecimal numbers, and strings starting with 0 represent octal numbers. After determining the radix, call the static method integer.valueof (String,int) method. Follow up on this approach.

Integer.valueOf(String,int)

public static Integer valueOf(String s, int radix) throws NumberFormatException {
    return Integer.valueOf(parseInt(s,radix));
}
Copy the code

Finally, the parseInt() method is called to get the corresponding int value, and integer.valueof (int) method is used to get the wrapped Integer object. Then look at the concrete implementation of integer.valueof (int).

Integer.valueOf(int)

Before we look at this method, let’s look at a classic interview question:

Integer b1 = 127;
Integer b2 = 127;

Integer c1 = 128;
Integer c2 = 128;

System.out.println(b1 == b2); // true
System.out.println(c1 == c2); // false
Copy the code

I believe you should have no doubt about the printed results. If in doubt, look at the source code with doubt.

To see how the above code works, use the javap command. Part of the bytecode is as follows:

21: bipush        127
23: invokestatic  #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
26: astore_1
27 bipush        127
29: invokestatic  #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
32: astore_2
33: sipush        128
36: invokestatic  #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
39: astore_3
40: sipush        128
43: invokestatic  #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
Copy the code

As you can see from the bytecode above, Java uses integer.valueof (int) to automatically box the base data type int. Integ. ValueOf (int)

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

The logic is clear: the value between integerCache. LOW and integercache. HIGH returns an object that has already been created in the cache, while the remaining values create new objects each time. LOW is -128, and integerCache. HIGH defaults to 127, which can be changed by setting -xx :AutoBoxCacheMax=

.

IntegerCache’s job is simply to fill the cache array with values when the VM loads the Integer class. The specific source code is as follows:

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(a) {}}Copy the code

Int = String; int = String;

toString() / toString(int)

public String toString(a) {
    return toString(value);
}
Copy the code
public static String toString(int i) {
    if (i == Integer.MIN_VALUE)
        return "2147483648";
    // Get the length. Negative numbers need +1 to indicate the sign '-'.
    int size = (i < 0)? stringSize(-i) +1 : stringSize(i);
    char[] buf = new char[size];
    getChars(i, size, buf);
    return new String(buf, true);
}
Copy the code

This is a carbon copy of the toString() method, which converts the current int value to a decimal string by default. This piece of source code is really the essence of the developers in order to improve the efficiency of the extreme, let people admire. Here’s a closer look at this method:

  1. forInteger.MIN_VALUE, return directly- 2147483648.
  2. throughstringSize()Method to get the desired string lengthsize
  3. New Character arraybufIs used to store strings
  4. throughgetChars()Method populates a character arraybuf
  5. throughStringThe constructor of the

The core functions are stringSize() and getChars().

stringSize(int)

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;
}
Copy the code

Gets the length of the decimal string corresponding to an int value. Only positive numbers are accepted. Ingenious use of a sizeTable array, loop matching, can be very convenient to obtain the corresponding string length. The sizeTable array has a maximum size of integer.max_value, which explains why integer.min_value is returned in step 1 and does not enter the stringSize() method.

getChars(int,int,char[])

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

    if (i < 0) {
        sign = The '-';
        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; }}Copy the code

The getChars() method really optimizes the runtime to the hilt. It simply fills each digit of the number I as a character into the character array BUf. If I were to implement it, it would be a version like this:

public static void getChars(int i, int index, char[] buf) {
    int q, r;
    for (int n = index - 1; n >= 0; n--) {
        q = i / 10;
        r = i - q * 10; i = q; buf[n] = digits[r]; }}Copy the code

Starting with the lowest digit of I, loop out and plug into buF. Yeah, it’s that simple logic, and the Integer source code has so many tricks to play with. Let’s take a closer look at how the source code implementation differs from my version.

In the source code to 65536 as the boundary, respectively, the execution of two different cycle body. Regardless of where this 65536 comes from, let’s take a look at these two loop bodies.

// Generate two digits per iteration
// Take the last two digits of I each time
while (i >= 65536) {
    q = i / 100;
// really: r = i - (q * 100);
    // r = i - (q * (2^6 + 2^5 + 2^2))
    r = i - ((q << 6) + (q << 5) + (q << 2));
    i = q;
    buf [--charPos] = DigitOnes[r]; // Mod operation
    buf [--charPos] = DigitTens[r]; // Divide
}
Copy the code

If you don’t know what it’s doing, debug it to make it clear. Each time the loop takes the last two digits of I as an int value r, and then performs r/10 and r%10 respectively to get the two digits. Source code clever use of two arrays, to avoid arithmetic, take a look at the two arrays:

final static char [] DigitOnes = {
    '0'.'1'.'2'.'3'.'4'.'5'.'6'.'7'.'8'.'9'.'0'.'1'.'2'.'3'.'4'.'5'.'6'.'7'.'8'.'9'.'0'.'1'.'2'.'3'.'4'.'5'.'6'.'7'.'8'.'9'.'0'.'1'.'2'.'3'.'4'.'5'.'6'.'7'.'8'.'9'.'0'.'1'.'2'.'3'.'4'.'5'.'6'.'7'.'8'.'9'.'0'.'1'.'2'.'3'.'4'.'5'.'6'.'7'.'8'.'9'.'0'.'1'.'2'.'3'.'4'.'5'.'6'.'7'.'8'.'9'.'0'.'1'.'2'.'3'.'4'.'5'.'6'.'7'.'8'.'9'.'0'.'1'.'2'.'3'.'4'.'5'.'6'.'7'.'8'.'9'.'0'.'1'.'2'.'3'.'4'.'5'.'6'.'7'.'8'.'9'};Copy the code

The DigitOnes array stores the result of mod 10 from 0 to 99.

final static char [] DigitTens = {
    '0'.'0'.'0'.'0'.'0'.'0'.'0'.'0'.'0'.'0'.'1'.'1'.'1'.'1'.'1'.'1'.'1'.'1'.'1'.'1'.'2'.'2'.'2'.'2'.'2'.'2'.'2'.'2'.'2'.'2'.'3'.'3'.'3'.'3'.'3'.'3'.'3'.'3'.'3'.'3'.'4'.'4'.'4'.'4'.'4'.'4'.'4'.'4'.'4'.'4'.'5'.'5'.'5'.'5'.'5'.'5'.'5'.'5'.'5'.'5'.'6'.'6'.'6'.'6'.'6'.'6'.'6'.'6'.'6'.'6'.'7'.'7'.'7'.'7'.'7'.'7'.'7'.'7'.'7'.'7'.'8'.'8'.'8'.'8'.'8'.'8'.'8'.'8'.'8'.'8'.'9'.'9'.'9'.'9'.'9'.'9'.'9'.'9'.'9'.'9'};Copy the code

The DigitTens array stores 0 to 99 divided by 10.

One more thing to note is this line of code:

/* * equals -> r = i - (q * (2^6 + 2^5 + 2^2)) * equals -> r = i - q * 100; * /
r = i - ((q << 6) + (q << 5) + (q << 2));
Copy the code

Use shift and addition instead of multiplication, which is also a detail to improve the operation efficiency, I believe that we should rarely think of in daily development. You can see something similar in the next loop. Here, a summary in advance:

  • Shift is more efficient than addition, subtraction, multiplication and division
  • Addition and subtraction are more efficient than multiplication and division
  • Multiplication is more efficient than division

For loops greater than 65536, let’s look at loops executed less than 65536:

// Fall thru to fast mode for smaller numbers
// assert(i <= 65536, i);
for (;;) {
    q = (i * 52429) > > > (16+3); // q = i * 10
    r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
    // r is the last digit of the number I
    buf [--charPos] = digits [r];
    i = q;
    if (i == 0) break;
}
Copy the code

Each time the last digit is fetched, it is inserted into the character array BUF. Given our experience with the body of the last loop, the first two lines of the body of the loop are easy to understand.

/* * equals -> (i * 52429) / 2^19 * equals -> (i * 52429) / 524288 * equals -> i / 10 */
q = (i * 52429) > > > (16+3);

/* * equals -> i - q * (2^3 + 2) * equals -> i - q * 10 */
r = i - ((q << 3) + (q << 1));
Copy the code

The first line uses multiplication and shift instead of division, and the second line uses addition and shift instead of multiplication.

Seeing this, you should have some questions, why 65536? Why 52429? Are these two numbers based on anything?

Let’s go back and think about it a little bit. Instead of saying (I * 52429) >>> (16+3), instead of saying (I * 52429) >>> (16+3), instead of saying (I * 52429) >>> (16+3), instead of saying (I * 52429) >>> (16+3), instead of saying (I * 52429) = (2 ^ 19) / 10 +1, Let’s list them:

2^ 10/10 + 1 = 103, 103/1024 = 0.100585938... 2^ 11/10 + 1 = 205, 205/2048 = 0.100097656... 2^ 12/10 + 1 = 410, 410/4096 = 0.100097656... 2^ 13/10 + 1 = 820, 820/8192 = 0.100097656... 2^ 14/10 + 1 = 1639, 1639/16384 = 0.100036621... 2^ 15/10 + 1 = 3277, 3277/32768 = 0.100006104... 2^ 16/10 + 1 = 6554, 6554/65536 = 0.100006104... 2^ 17/10 + 1 = 13108, 13108/131072 = 0.100006104... 2^ 18/10 + 1 = 26215, 26215/262144 = 0.100002289... 2^ 19/10 + 1 = 52429, 52429/524288 = 0.100000381... 2^ 20/10 + 1 = 104858, 104858/1048576 = 0.100000381... 2^ 21/10 + 1 = 209716, 209716/2097152 = 0.100000381... 2^ 22/10 + 1 = 419431, 419431/4194304 = 0.100000143...Copy the code

As can be seen from the above calculation results, the accuracy will be higher when it is greater than or equal to 19. If we take 20 here, the equation is:

q = (i * 104858) >>> 20
Copy the code

So, what is the value of I that separates the two loops? Note that this is an unsigned right shift, so I * 104858 can theoretically reach the maximum value of unsigned int 2^32-1, i.e. 4294967295. The separator value I cannot be greater than (2^32-1) / 104858 = 40659, which is less than 65536. If we take 21, the partition value I can’t be greater than (2^32-1) / 209716 = 20479, so it’s a little bit smaller. Obviously, choosing 19 ensures both the highest accuracy and the highest separation value. (2^32-1) / 52429 = 81919, no more than 81919, from the execution efficiency, the source code to choose 65536 this number.

In summary, there is a combination like this, 65536, 52429, 19. Finally, there is a question, the source code is not directly written 19, but instead of 16 + 3, this can also improve the efficiency of the operation?

toString(int,int)

The toString(int) method examined above specifies conversion to a decimal string. We can also use the two-argument toString() method to convert to a specified decimal string. The code is relatively simple, directly in the source code comments.

public static String toString(int i, int radix) {
    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
        radix = 10; // Set illegal base to 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; }// Cyclic radix remainder
    while (i <= -radix) {
        buf[charPos--] = digits[-(i % radix)];
        i = i / radix;
    }
    buf[charPos] = digits[-i];

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

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

toUnsignedString(int)

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

Convert to an unsigned string, convert to long here and then call long.tounsignedString () without doing too much analysis here.

getInteger()

Finally, there is a getInteger() method, which is not used very much, to get the int value specified by the system property. Take a look at a simple example:

Properties properties = System.getProperties();
properties.put("luyao"."123456");
System.out.println(Integer.getInteger("luyao"));
System.out.println(Integer.getInteger("luyao".0));
System.out.println(Integer.getInteger("luyao".new Integer(0)));
Copy the code

The print is always 1234. The difference is that the latter two methods provide a default value when the specified attribute name does not exist, and the first method returns NULL.

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;
}
Copy the code

You can see that you are actually calling the integer.decode () method, which you have already analyzed and won’t go into here.

So much for converting from String to int, and I think most of them have already been covered. And finally, a little bit about bit operations.

An operation

Class notes mention a book, Henry S. Warren Jr. Hacker’s Delight, in which Integer’s bit operations are described. I only explain the function of the method here, and I will write about the detailed principle separately.

Int highestOneBit(int I) : returns an int lowestOneBit(int I) : returns an int lowestOneBit(int I) : Int numberOfLeadingZeros(int I) instead of highestOneBit(), take the lowest right of its binary complement 1, and fill the rest with 0: Int numberOfTrailingZeros(int I): returns the number of zeros after the lowest 1 int bitCount(int I): Int rotateRight(int I, int distance) : Int rotateLeft(int I, int distance); Reverse (int I) : reverses binary complement int signum(int I) : returns 1 for positive numbers, -1 for negative numbers,0 for negative numbers int reverseBytes(int I) : Inverts a binary complement in bytesCopy the code

conclusion

A small Integer class that took a long time to Read from beginning to end. Again, Read the fuck sorce code! Source code can give you more feedback than you’d expect.

Portal: Annotated integer.java source code

Article update on wechat public number: Bingxin said, focus on Java, Android original knowledge sharing, LeetCode solution, welcome to pay attention to!