[JAVA] I read the source of Integer

I decided to read the JDK source somehow. That said, I don't have time to read each line carefully, so I read it briefly and found this code. Last time I read the source of Short, so next is Integer.

Integer class

The Integer class is a wrapper class for the primitive type int. First, the fields and the constructor. Well, it's a source that everyone can imagine.

Integer.java


    private final int value;

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

IntegerCache class

Actually, there is an IntegerCache class that is not visible in javadoc.

Integer.java


    /**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */

    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() {}
    }

Byte, Short came and changed. Since this inner class is private, you can't usually read what is written in the javadoc comment. It seems that you can increase the upper limit from 127 with the startup option -XX: AutoBoxCacheMax = size. According to Numeric cache, it was added from JDK 1.6.

Let's check the source of JDK 1.5.

Integer.java


    private static class IntegerCache {
        private IntegerCache(){}

        static final Integer cache[] = new Integer[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Integer(i - 128);
        }
    }

Oh, it's refreshing. Like Byte and Short, it was from -128 to 127. Although it is IntegerCache, it is referenced by valueOf like Byte and Short.

Integer.java


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

Compare with the comparison operator ==

As with Short, compare the instances with 127 and 128.

Main.java


	public static void main(String[] args) {
        int i00 = 127;
        Integer i01 = Integer.valueOf(i00);
        Integer i02 = i00;
        System.out.println(i01 == i02);
        int i10 = 128;
        Integer i11 = Integer.valueOf(i10);
        Integer i12 = i10;
        System.out.println(i11 == i12);
	}

When you run ...

$ java Main
true
false

$ java -XX:AutoBoxCacheMax=127 Main
true
false

$ java -XX:AutoBoxCacheMax=128 Main
true
true

Boot option -XX: AutoBoxCacheMax is working.

Hacker's Delight source

In the Japanese translation of javadoc, "Notes on implementation: The implementation of the" bit twiddling "method (highestOneBit and numberOfTrailingZeros) is" Hacker's Delight "(Addison Wesley, 2002) by Henry S. Warren, Jr. ) It is based on. "is what it reads. Since it's from JDK 1.5, many of you probably know it, but let's search the source for the "HD" string.

Integer.java


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

bitCount feels like a bit when you look at the Algorithm for counting / searching bits. It seems to be much faster than looping and counting by yourself. When do you use the problem ... highestOneBit was solving the problem and I had the opportunity to use it. → Xmas Contest 2016 / A --Array Sum

Methods added in JDK 1.8

There are quite a lot, so I picked up only three.

Integer.java


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

I don't really need it. If you want to make it anyway, you should make an int version of Math.pow (). (1/13 postscript) Well, if it is sum, if it is a method that has devised such as skipping an exception when it overflows, it is still worth the existence, but what about a method that just returns a + b? And since it's an Integer class, non-static methods like Integer add (Integer other) come in nicely ... (1/13 postscript) @see java.util.function.BinaryOperator is written in the javadoc comment, but did it make sense?

parseUnsignedInt method

(1/13 postscript) I skipped it lightly, but I added it by looking at Long.parseUnsignedLong.

Starting with JDK 1.8, parseUnsignedInt has been added. Isn't java int signed? What does it mean to parse it unsigned?

Integer.java


    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 == '-') {
                throw new
                    NumberFormatException(String.format("Illegal leading minus sign " +
                                                       "on unsigned string %s.", s));
            } else {
                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) {
                        return (int) ell;
                    } else {
                        throw new
                            NumberFormatException(String.format("String value %s exceeds " +
                                                                "range of unsigned int.", s));
                    }
                }
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
    }

I wondered if I could write 0xffff_ffff_0000_0000L, but if it was a value of only the lower 32 bits, I would cast it with an int. In other words, even if the sign bit is set, it will be cast as an int, so it will be negative. It parses unsigned, but it can be negative. It's a great specification.

Let's try it.

Main.java


    public static void main(String[] args) {
        int i01 = Integer.parseUnsignedInt("2147483647");
        System.out.println(i01);
        int i02 = Integer.parseUnsignedInt("2147483648");
        System.out.println(i02);
        int i03 = Integer.parseUnsignedInt("4294967295");
        System.out.println(i03);
        int i04 = Integer.parseUnsignedInt("4294967296");
        System.out.println(i04);
    }

When you run ...

2147483647
-2147483648
-1
Exception in thread "main" java.lang.NumberFormatException: String value 4294967296 exceeds range of unsigned int.
	at java.lang.Integer.parseUnsignedInt(Integer.java:684)
	at java.lang.Integer.parseUnsignedInt(Integer.java:711)
	at Main.main(Main.java:9)

The result is as expected, but are you happy? this. If you want to use 32-bit full, you can use long.

Finally

There is parseUnsignedInt in the methods added in JDK 1.8, but I feel that there are many static methods. (1/13 postscript) There were 37 public static methods in JDK 1.8. I think it would be better to separate it into the IntegerUtil class if there is such a thing. By the way, it was 13 in JDK 1.4. Once upon a time I thought it was a simpler class.

Suddenly I noticed that the hard tab width is supposed to be 4 characters. Once upon a time, the width of the hard tab was 8 characters, one indent was 4 blanks, 2 indents were 1 hard tab, 3 indents were 1 hard tab + 4 blanks, and 4 indents were 2 hard tabs.

Comparing the old sauces, --JDK 1.4 Sun Microsystems Hard tab 8 characters --JDK 1.5 Sun Microsystems Hard tab 8 characters --JDK 1.6 Oracle Hardtab 8 characters --JDK 1.7 Oracle Hard Tab 4 Characters --JDK 1.8 Oracle Hardtab 4 characters And the style has changed from JDK 1.7. (1/13 postscript) I thought that the hard tab width of 8 characters would be about assembly language, so I replaced all the hard tabs with 8 blank characters. I thought Sun Microsystems was a good company, but I've always thought that this style was crazy.

List of public static methods in JDK 1.8

(1/13 postscript) I grep, so paste it public static String toString(int i, int radix) { public static String toUnsignedString(int i, int radix) { public static String toHexString(int i) { public static String toOctalString(int i) { public static String toBinaryString(int i) { public static String toString(int i) { public static String toUnsignedString(int i) { public static int parseInt(String s, int radix) public static int parseInt(String s) throws NumberFormatException { public static int parseUnsignedInt(String s, int radix) public static int parseUnsignedInt(String s) throws NumberFormatException { public static Integer valueOf(String s, int radix) throws NumberFormatException { public static Integer valueOf(String s) throws NumberFormatException { public static Integer valueOf(int i) { public static int hashCode(int value) { public static Integer getInteger(String nm) { public static Integer getInteger(String nm, int val) { public static Integer getInteger(String nm, Integer val) { public static Integer decode(String nm) throws NumberFormatException { public static int compare(int x, int y) { public static int compareUnsigned(int x, int y) { public static long toUnsignedLong(int x) { public static int divideUnsigned(int dividend, int divisor) { public static int remainderUnsigned(int dividend, int divisor) { public static int highestOneBit(int i) { public static int lowestOneBit(int i) { public static int numberOfLeadingZeros(int i) { public static int numberOfTrailingZeros(int i) { public static int bitCount(int i) { public static int rotateLeft(int i, int distance) { public static int rotateRight(int i, int distance) { public static int reverse(int i) { public static int signum(int i) { public static int reverseBytes(int i) { public static int sum(int a, int b) { public static int max(int a, int b) { public static int min(int a, int b) {

List of public static methods in JDK 1.4

(1/13 postscript) I grep, so paste it public static String toString(int i, int radix) { public static String toHexString(int i) { public static String toOctalString(int i) { public static String toBinaryString(int i) { public static String toString(int i) { public static int parseInt(String s, int radix) public static int parseInt(String s) throws NumberFormatException { public static Integer valueOf(String s, int radix) throws NumberFormatException { public static Integer valueOf(String s) throws NumberFormatException public static Integer getInteger(String nm) { public static Integer getInteger(String nm, int val) { public static Integer getInteger(String nm, Integer val) { public static Integer decode(String nm) throws NumberFormatException {

Recommended Posts

I read the source of Integer
I read the source of ArrayList I read
I read the source of Long
I read the source of Short
I read the source of Byte
I read the source of String
I read the Kotlin startbook
Is drainTo of LinkedBlockingQueue safe? I followed the source
05. I tried to stub the source of Spring Boot
I investigated the internal processing of Retrofit
[day: 5] I summarized the basics of Java
Read the Perelman treatise of Poincare conjecture
I checked the place of concern of java.net.URL # getPath
I understood the very basics of character input
I compared the characteristics of Java and .NET
I want to var_dump the contents of the intent
I touched on the new features of Java 15
I tried using the profiler of IntelliJ IDEA
I checked the number of taxis with Ruby
Try the free version of Progate [Java I]
[Java] How to get the URL of the transition source
I examined the life cycle of the extension of JUnit Jupiter
The world of clara-rules (2)
I tried using the Server Push function of Servlet 4.0
I read the readable code, so make a note
I was addicted to the record of the associated model
I tried to summarize the state transition of docker
I saw the list view of Android development collectively
[Java] Integer information of characters in a text file acquired by the read () method
Judgment of the calendar
I tried the new feature profiler of IntelliJ IDEA 2019.2.
The world of clara-rules (4)
I want to know the answer of the rock-paper-scissors app
Image processing: The basic structure of the image read by the program
I want to display the name of the poster of the comment
I summarized the display format of the JSON response of Rails
The world of clara-rules (1)
The world of clara-rules (3)
Read Java HashMap source
I read the "Object-Oriented Practical Guide", so a memorandum
Source of cellular objects
Read the Rails Guide (Overview of Action Controller) again
[Java] When writing the source ... A memorandum of understanding ①
I wrote a sequence diagram of the j.u.c.Flow sample
The world of clara-rules (5)
I summarized the types and basics of Java exceptions
The idea of quicksort
[WIP] I tried the configuration of Docker + Streama + NFS
I am keenly aware of the convenience of graphql-code-generator, part 2
I can't get out of the Rails dbconsole screen
I learned about the existence of a gemspec file
I want to be aware of the contents of variables!
I want to return the scroll position of UITableView!
The idea of jQuery
I made the server side of an online card game ①
I didn't understand the behavior of Java Scanner and .nextLine ().
I took a peek at the contents of Java's HashMap
I tried to summarize the basics of kotlin and java
Now, I understand the coordinate transformation method of UIView (Swift)
[Android] Exit the activity of the transition source at the time of screen transition
I want to expand the clickable part of the link_to method