Java SE consolidation (a): primitive wrapper class source code interpretation

Java variable types can be divided into two categories: primitive types and reference types. There are eight basic types, namely, short, int, long, byte, char, float, double, boolean, but also there are 8 types of reference as its packaging, e.g. Integer, Double like. This article is to discuss these primitive types and their wrapper classes.

The following section relates to source is only a representative list of some of the source, there will be no large chunks of code. JDK version I am using JDK1.8_144

1 Integer (plastic)

Integer is the basic type int type of packaging. Below is their inheritance system:

ilIpdA.png

Integer Number inherited class that implements the Comparable can, with comparable ability, but also indirectly achieve Serializable interface that is serializable. The actual figures related to several other packaging types are inherited such a system, so if there are no special instructions below, it means the same inheritance system and Integer.

Let's look at valueOf () method, there are three overloaded valueOf in the Integer class () method, but eventually will be called public static Integer valueOf (int i). The following is a public static Integer valueOf (int i) source:

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

It can be seen that accepts a basic type int argument and returns an Integer object should be noted that if the judge, here i will determine whether this [IntegerCache.low, IntegerCache.high] interval, if the direct return the cached value, then this value is low and hight is how much? We look to IntegerCache 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() {}
    }
复制代码

Integer This is an internal static class, from the code, it is easy to see that the low value of -128, a default value is 127 high, which high value can be set by java.lang.Integer.IntegerCache.high property, class the logic of the code block where almost all static, that is to say when the class loader will be carried out, the results of the implementation of what is it? Watch these lines of code:

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

The interval [low, hight] values ​​are configured Integer object and stored in the cache array. This time to look back at the valueOf () method, if the value of the parameter i found in [low, hight] in the interval, it will return an Integer object in the corresponding cache, then words, if the argument in this interval in the range, then this method is called when you do not need to create objects, and direct use of the cache objects, reducing the overhead of creating objects.

Then why should it be so complicated? Because Java5 provides automatic syntax sugar boxing and auto-unboxing, and this method is actually automatic packing services (you can see from the comments, this method java5 started from there, and should thus be inferred automatic loading unpacking boxes mechanisms), Integer is a very popular class, with this caching mechanism, each time you do not need to create objects in automatic or manual packing call time, greatly improving the object reuse rate, but also provides operating efficiency. [-128,127] is a more conservative range, the user can modify the high value by modifying java.lang.Integer.IntegerCache.high, but preferably not too much, because after all Intger object is also to take up a lot of memory, If the upper bound is set too high, and do not often use large value, then the cache on some more harm than good.

Let's look at another method intValue (), this method is very simple:

    public int intValue() {
        return value;
    }
复制代码

Integer value is a private class field, type int, is to represent the actual value, which is actually a method to automatically When unpacking the call.

Other methods have nothing to be said, are some of the most functional methods (such as max, min, toBinaryString) and constants (such as MAX_VALUE, MIN_VALUE), and interested friends can view their own algorithm logic is not difficult.

Several other is not to say, after understanding the Integer source, others are not difficult to understand.

Automatic boxing and unboxing 2 Automatic

Auto-boxing and auto-unboxing is syntactic sugar Java5 provided when we need to be compared, assignment and other operations between primitive types and wrapper classes, the compiler will automatically help us typecast, boxing is the basic type conversion into packaging type, unpacking process is a contrary. For example, we have the following code:

public static void main(String[] args) {
    List<Integer> list = new ArrayList<>();
    int a = 1, b = 2, c = 3;
    list.add(a);
    list.add(b);
    list.add(c);
}
复制代码

Content .class files compiled as follows (do transcoding, in fact .class bytecode files should be, but for ease of viewing, it will be their turn form became java code):

public static void main(String[] var0) {
    ArrayList var1 = new ArrayList();
    byte var2 = 1;
    byte var3 = 2;
    byte var4 = 3;
    var1.add(Integer.valueOf(var2));
    var1.add(Integer.valueOf(var3));
    var1.add(Integer.valueOf(var4));
}
复制代码

Here boxing operation occurs, the compiler help us call Integer.valueOf () method to convert the int type Integer List to suit the type of container (container type parameter can not be a basic type).

Unpacking is also similar, but opposite directions and packing it, generally occurs when the value assigned to the type of packaging of the basic type, for example:

Integer a = 1;
int b = a; //自动拆箱
复制代码

If not unpacking, the above code is certainly not compile because the types do not match, and no strong turn.

About automatic boxing and unboxing more content, the Internet has a lot of information (very, very much), it is recommended interested friends can go online to search search.

3 Select the basic type or types of packaging it?

First, let's define a basic principle: If a scene can not use one of the basic types and package types, then you can choose another. For example, the generic type parameter can not be a basic type of container, then you do not have any hesitation, the direct use of packaging type it.

When both types are available, it is recommended to use basic types, the following three main reasons:

  1. Packing type is a class that you want to use a value it is necessary to create an object, even if there are situations cache saves time overhead of creating objects, but there is still space overhead, a first object contains the object, and the object instance data filling, but in fact we need only instance data only for Integer, we only need to value value field only, that is to say the use of primitive type int only takes up 4 bytes of space, and the need to use the object several times the basic types space (you can calculate).

  2. Next article 1, there is a possible target value determination null to null, so that when its use sometimes have, fortunately few, when the service logic when a complex (or programmers to write code written on top of the time ), it is very easy to miss, once missing it is very possible null pointer exception if not rigorous testing, not be able to really test it out.

  3. Packaging operations when making comparisons sometimes confusing, we give an example, suppose you have the following code:

        public static void main(String[] args) {
            Integer d = 220;  
            Integer e = 220;
            int f = 220;
            System.out.println(d == e);
            System.out.println(e == f);
        }
    复制代码

    If you have not encountered such a problem, the results may subconsciously say is true and true executed, but in fact, the resulting output is false, true. why? For the first comparison, d and e are Integer object, the direct comparison with the value == actually referenced, rather than the actual value, through the automatic packing 220 actually occurs in the time assigned to them, i.e., call over valueOf () method, while the 220 range beyond the default cache, it will create a new Interge objects, both a and b of reference is certainly not equal, it will output false. Second comparison, f is the basic type, in this case, happens automatically unpacking, actually on both sides of the basic variable types == int, there is no problem when the direct comparison, the output result will be true.

In short, if they can use basic types, it is best to use basic types, rather than the packaging, if it is unable to use basic types, such as generic type parameter container, only use packaging.

4 Summary

This article describes the Integre packaging, a simple analysis of its source code, there is no reason why the analysis because their implementation is very similar, repeat no fun introduction to other types of guarantee basic class. Also briefly discussed about the automatic packing and unpacking automatic, this feature is convenient for programmers to improve the efficiency of development, but the problem if used improperly can cause confusing, considered the pros and cons of it. The choice between the basic types and package types, I tend to use Basic types and causes of the text is also a more detailed explanation.

Guess you like

Origin juejin.im/post/5d6e8091518825753553d95c