Java source code analysis part 1-Java numerical type

Source: Internet
Author: User

This article mainly introduces the Integer type commonly used in Java-Integer

First, bitwise operations are widely used. Such applications can be seen everywhere, whether it is the written examination, interview, or Java source code of famous enterprises. I don't want to talk too much about bitwise operations. I would like to recommend a very good blog post. The address is as follows:

Http://blog.csdn.net/morewindows/article/details/7354571

Similarly, in the source code of the Integer. java class, Java designers use a large number of bitwise operations to improve efficiency. First, let's look at a simple hexadecimal conversion source code:

// Unsigned integer in hexadecimal notation, move four public static String toHexString (int I) {return toUnsignedString (I, 4) to the right;} // unsigned integer in octal format, move three places to the right: public static String toOctalString (int I) {return toUnsignedString (I, 3);} // unsigned integer, in hexadecimal format, move two places to the right: public static String toBinaryString (int I) {return toUnsignedString (I, 1) ;}// convert the unsigned integer to private static String toUnsignedString (int I, int shift) {char [] buf = new char [32]; int charPos = 32; int radix = 1 <shift; int mask = radix-1; do {buf [-- charPos] = digits [I & mask]; I >>> = shift; // I = I >>> shift} while (I! = 0); return new String (buf, charPos, (32-charPos ));}
Let's take a look at the hexadecimal conversion of a 10-digit unsigned integer. Due to the lack of boundary check, the toUnsignedString () method is not public, but multiple common hexadecimal conversion methods are provided. Finally, the converted string representation is returned. The reason why a 32 character array should be defined in the source code will be analyzed later.

We know that the int value type in Java occupies 4 bytes. Sometimes we need to perform some special processing on the 4 bytes that represent an int value, such as byte inversion and bit inversion, the source code is as follows:

// Reverse the order of 4 bytes, not reverse the position. public static int reverseBytes (int I) {return (I >>> 24 )) | (I> 8) & 0xFF00) | (I <8) & 0xFF0000) | (I <24 ));} // reverse the position. 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 & 0x0f0f0f) <4 | (I >>> 4) & 0x0f0f0f; I = (I <24) | (I & 0xff00) <8) | (I >>> 8) & 0xff00) | (I >>> 24); return I ;}

You can take a good look at how the above Code implements their functions. Continue with the following two methods:

   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) {        return i & -i;    }

HighestOneBit () is used to take the highest bid on the left of the binary form of I and complete the zeros after the high bits. Finally, the result of the int type is returned. LowestOneBit () is naturally the result of taking the first 1 on the rightmost side and putting all the values above 0. Some other methods are provided in the Code class. These methods also use a lot of bit operations. If you are interested, you can check them yourself.
Let's take a look at other important methods in the class.

// The following ASCII characters may be expressed as numbers. 26 characters and 10 digits, which are 36 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 static String toString (int I, int radix) {// The value of the base must be in the if (radix <Character. MIN_RADIX | radix> C Haracter. 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; // when I is a positive number, it becomes a negative 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 ));}
The source code snippet above first defines an array of digits characters, which can represent numerical values. For example, in hexadecimal notation, a can represent 10, B can represent 11, 26 letters can also represent a two-digit integer, plus 10 digits, A total of 32 characters can be used to represent numerical values. It can be seen that the maximum hexadecimal value supported in Java is 32. If it is greater than 32, it is processed in decimal format. Next, we will use the toString () method to convert the I in decimal format to the base number of radix and return the result in the form of a string. The following test code:
System.out.println(Integer.toString(13,19));System.out.println(Integer.toString(173,29));
Run the following results: d // 13 5S // 5*29 + 28

Note the implementation code of the toString () method. You can see that for a signed number I, all of them are converted to negative numbers for hexadecimal conversion, in this way, the signed number can be processed in a unified manner. Can it be converted to a positive number for processing? At this time, we need to consider the border issue. For example, if the byte type represents a minimum integer of-128, and the maximum integer is 127, then converting the negative number into a positive number will go beyond the range indicated by the type, the truth here is the same.
Continue to read the source code of another toString () method:

Public static String toString (int I) {if (I = Integer. MIN_VALUE) return "-2147483648"; // For example, if it is 9, the size is 1, and if it is-9, it is 2, also store a "-" int size = (I <0 )? StringSize (-I) + 1: stringSize (I); // calculate the size of the character array required to save the integer. char [] buf = new char [size]; getChars (I, size, buf); return new String (0, size, buf);} // The following storage is a 10-digit final static int [] sizeTable = {9, 99,999,999 9, 99999,999 999, 9999999,999 99999, 999999999, Integer. MAX_VALUE}; // The maximum value of MAX_VALUE is 2147483647 // Requires positive x static int stringSize (int x) {for (int I = 0; I ++) if (x <= sizeTable [I]) return I + 1 ;}
The function is to convert a signed integer to a string. First, convert the integer to a character array, and then convert the character array to a string. the source code of the getChars () method is as follows:

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', '4', '4', '4', '4', '4', '4', '4', '4', '4 ', '4', '4', '5', '5', '5', '5', '5', '5 ', '5', '5', '6', '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 ',}; 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',}; 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 // Number of the maximum number range in which more than four words can be processed, that is, while (I> = 65536) {// 2 ^ 16 = 65536 q = I/100; // 2 ^ 6 + 2 ^ 5 + 2 ^ 4 = 100 r = I-(q <6) + (q <5) + (q <2); // equivalent to r = I-(q * 100); I = q; buf [-- charPos] = DigitOnes [r]; buf [-- charPos] = DigitTens [r];} // Fall thru to fast mode for smaller numbers 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 ;}}

In order to quickly convert a value to a character type, the program uses the space-to-time policy and uses arrays to store the required data.

I am in a rush to see this code. I have not figured out the main issues:

(1) Why should we separate numbers greater than and less than 65536?

(2) q = (I * 52429) >>> (16 + 3) not familiar

Which of the following great gods is grateful to you ~~~

Okay, let's continue to look at it. Another major method is decode (). The source code is as follows:

 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;    }

The function above is to convert a string to an integer and accept a string written in octal, decimal, or hexadecimal format. Test the above method:

System.out.println(Integer.decode("0x0011"));System.out.println(Integer.decode("0X0011"));System.out.println(Integer.decode("011"));System.out.println(Integer.decode("-011"));
The final running result is as follows: 19 19 9-9

The values represented by valid strings are finally returned in decimal format, or you can use the parseInt () method. The source code is as follows:

 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) {            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");        }        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);            if (firstChar < '0') { // Possible leading "+" or "-"                if (firstChar == '-') {                    negative = true;                    limit = Integer.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;    }
This function is public, so the boundary condition check is very strict. Returns the result of converting the specified hexadecimal signed integer to a decimal integer. The test code is as follows:

parseInt("0", 10) returns 0parseInt("473", 10) returns 473parseInt("+42", 10) returns 42parseInt("-0", 10) returns 0arseInt("-FF", 16) returns -255parseInt("1100110", 2) returns 102parseInt("2147483647", 10) returns 2147483647parseInt("-2147483648", 10) returns -2147483648parseInt("2147483648", 10) throws a NumberFormatExceptionparseInt("99", 8) throws a NumberFormatExceptionparseInt("Kona", 27) returns 411787
Note that:

ParseInt ("Kona", 10) throws a NumberFormatException // an exception occurs because K characters are not allowed in decimal format.
An error occurs in the program because only numbers ranging from 0 to 9 can be displayed in the decimal value, which is determined mainly by the Character. digit () function. The source code of this function will be parsed in the character source code analysis.



















Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.