Do you really understand Java in the Long Well?

The actual development, we use the Long types of situations should be very much. But, you really fully grasp the Long type thing?

Test code

First, we look at a test code. This code can be tested.

    @Test
    public void testLong() {
        long primaryLong = 127L;
        Long long1 = Long.valueOf(primaryLong);
        Long long2 = 127L;

        Assert.assertTrue(long1 == long2); // 1

        long1 = new Long(127L);
        Assert.assertFalse(long1 == long2); // 2

        primaryLong = 128L;
        long1 = Long.valueOf(primaryLong);
        long2 = 128L;

        Assert.assertFalse(long1 == long2);  // 3

        long1 = new Long(128L);
        Assert.assertFalse(long1 == long2);  // 4
    }
复制代码

In the above test code, we compare the equality between the two types of variables long1 Long and Long2, here we use the "==" operator, the address used to test two variable references are equal.

Senior code farmers should have created a Long There are three ways: new Long (), Long.valueOf () and automatic packing. The code demonstrates the results were obtained in three ways.

  • Analysis code Note 1 returns to true. This shows that when using the value 127L, regardless Long.valueOf Long variable assignment to create or use autoboxing long into a Long type, two variables point to the same location.
  • Analysis of code Note 2 returns false. This shows that the use of new creation out of Long (127L) Long variable, with just the use of automatic packing created Long variables no longer point to the same location.
  • Analysis 3,4 code Note returns to false. This shows the value in use 128L create Long variables, each pointing to a different location, whether it is new Long, Long.valueOf or automatic packing.

How is this going? Especially for Long.valueOf or automatic packing of these two methods, it is actually in 127L and 128L when the result is not the same?

In order to completely understand why the above code is such a result, we had to start from the source code.

analysis

We java.lang.Long open source code. Wherein the key code is as follows.

public final class Long extends Number implements Comparable<Long> {
    private final long value; // 1

    private static class LongCache { // 2
        private LongCache(){} // 2.1

        static final Long cache[] = new Long[-(-128) + 127 + 1]; // 2.2

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

    @Deprecated(since="9")
    public Long(long value) { // 3
        this.value = value;
    }

    @Deprecated(since="9")
    public Long(String s) throws NumberFormatException { // 4
        this.value = parseLong(s, 10);
    }

    public static Long valueOf(long l) { // 5
        final int offset = 128;
        if (l >= -128 && l <= 127) { // will cache
            return LongCache.cache[(int)l + offset];
        }
        return new Long(l);
    }
}
复制代码
  • Long Number class inherits from the base class, an abstract class is a class Number, the number of representatives. The following figure shows the Integer, Long, Byte, Short, Float and Double inherit from Number.

    Only some kind of abstract methods XXXValue. As shown below.

  • Analysis of Long Note 1 represents an internal actually store or a variable value, to store the original data type long.

  • Note analysis is 3,4 Long two construction method, two methods are of value assignment, no other processing.

  • We look Analysis Note 2 and 5: Analysis Note 2 is an internal static class LongCache, Judging from the name, the class should be a Long types of caching:

    • Note analysis indicates 2.1 LongCache a private constructor, to prevent instances of that class. private constructor is typically used in tools or single-instance class, e.g. common single mode embodiment requires private constructor.
    • 2.2 Analysis of expressed NOTE class has a Long array cache, and with static final modification. The size of the array -(-128) + 127 + 1=256.
      The final array with a initialized you can not re-assign them, but still can modify the reference value of each element of the array to cache the next target.
    • 2.3 Analysis of expressed cache Note initialized. 0-256 subscripts are initialized to a value between -128 and 128.
  • Next, analysis see Note 5, when the parameter l is a value between -128 and 127, returns the value of the direct LongCache internal cache array corresponding to the subscript. Here the offset is very clever set 128, thereby setting the minimum index value is -128 (int) l + offset = 0. It does not belong to [-128, 127] range of such values, the new Long call returns.

  • At the same time, pay attention to the construction method of the @Deprecated(since="9")annotation indicating JDK9 from the start, the constructor has not been recommended. JDK documentation, it is recommended to use a static factory method to construct Long.valueOf Long object that can get a better space and time performance.

According to standard grammar, automatic packaging actually calls is Long.valueOf, rather than the constructor.

The foregoing analysis, the value for [-128, 127], whether or automatically using Long.valueOf packing, are ultimately subject to read the value LongCache.cache with it, and therefore "==" is true. Other cases, 2 of each different variable "==" comparison is false.

expand

  • For Short class, and the class source code ShortCache valueOf methods and implement a Long identical. Here not carried out.
  • For Byte class, only to receive a value between 127 -128. valueOf method can return all values ​​ShortCache.cache.
  • For Float and Double classes, no so-called FloatCache and DoubleCache, so every time a new object is constructed.
  • In order to avoid differences in result "==" appearing in the above code comparison appears. Comparison between the recommendation object, use or equals to the original type of removable packaging reuse "==" comparison, the above test code can be used long1.longValue () or the Long + long1 then converted to long use "==" comparison

Note, + long1 must ensure that the + long1 not return null. Otherwise it will be reported NullPointerException.


Here a little test to see how we understand?

Long long1 = new Long(100L);
Long long2 = 100L;
Long long3 = 100L;
Long long4 = 128L;
Long long5 = 128L;

System.out.println(long1 == long2);
System.out.println(+long1 == long2);

System.out.println(long2 == long3);
System.out.println(+long2 == long3);

System.out.println(long4 == long5);
System.out.println(+long4 == long5);
复制代码

What do you think the above code output?

answer

false
true
true
true
false
true
复制代码

Guess you like

Origin juejin.im/post/5e6ada0fe51d45271849f498