Java utility classes — wrapper classes

As we all know, the JDK actually gives us many, many Java developers have written the ready-made class, they all can understand into a utility class, such as our common collection classes, date related classes, math related classes and so on, with these tools, you will find that it can greatly save time, can easily achieve your requirements. Of course, you can fulfill your requirements without these packages, but you need time, and today we are going to focus on the packaging class.

I. Introduction of packaging

1. Why is the packaging class needed?

We know that the Java language is an object-oriented programming language, but not the basic data types in the Java object oriented, but we in be used actually often need to convert basic data types into objects, convenience of operation, for example, a collection of operations, at this time, we need the basic types of data into objects, That’s where the wrapper class comes in.

2. What is the packaging class?

The wrapper class, as the name suggests, is the class that wraps what, so what wraps what, obviously this is the class that wraps the base type. The purpose of a wrapper class is to turn a primitive type into an object and treat the primitive type as an object.

In Java, we know that there are eight basic data types, so there are eight corresponding wrapper classes, the wrapper class is the basic type name begins with a capital letter. The exceptions are Integer and Character, which display the full name, as shown in the table below:

Basic data types Corresponding packaging class
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

Ii. Inheritance relationship of packaging class

By reading the Java8 API documentation or looking at the source code, we can see the inheritance relationship of the eight wrapper classes as follows:

From the inheritance diagram above, we can actually remember that there are 6 numeric related elements in the wrapper class inherited from the Number class, and the other two are not numeric related elements inherited from the Object class by default. We can also see from the OFFICIAL API documentation that the eight wrapper classes all implement the Serializable, Comparable interface. Such as the Integer class shown below

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

Iii. Use method of packaging class (basic operation)

For the rest of the presentation on wrapping classes I’m going to cover the Integer wrapper class, and so on. The usage and operations are pretty much the same, but the names are different.

1. Wrapper class constructor

Each of the eight wrapper classes has its own constructor with arguments of the corresponding type. Eight of the wrapper classes have constructor overloads in addition to Character, with arguments of type String.

Integer one = new Integer(666);
Integer two = new Integer("666");Copy the code

2. Automatic unpacking for packaging

Before we know about automatic unpacking, we need to know what unpacking and packing are. In fact, unpacking mainly deals with the conversion of basic types and packaging types.

  • Boxing: The process of converting a base type to a wrapper type is called boxing.

  • Unpacking: The process of converting a package type to a base type is called unpacking.

In fact, before JDK1.5, there was no automatic unboxing, developers had to do it manually:

// Manually boxing, that is, converting base type 10 to reference type Integer Integer = new Integer(10); Integer1 = integer.valueof (10); Int num = integer.intValue();Copy the code

After JDK1.5, auto-boxing and auto-unboxing are available to reduce developer work. Automatic unpacking and automatic packing are realized, as shown in the following code:

Integer one = 1; Int two = one + 10;Copy the code

In fact, the above two ways are essentially the same, but one is automatic implementation, a manual implementation. As for how to realize the automatic unpacking I will not do in-depth research here.

Fourth, the caching mechanism of the wrapper class

Let’s start with the following code, Example 1:

public static void main(String[] args) { Integer i1 = 100; Integer i2 = 100; Integer i3 = new Integer(100); Integer i4 = new Integer(100); System.out.println(i1 == i2); //true System.out.println(i1 == i3); //false System.out.println(i3 == i4); //false System.out.println(i1.equals(i2)); //true System.out.println(i1.equals(i3)); //true System.out.println(i3.equals(i4)); //true }Copy the code

When we change the value to 200, example 2:

public static void main(String[] args) { Integer i1 = 200; Integer i2 = 200; Integer i3 = new Integer(200); Integer i4 = new Integer(200); System.out.println(i1 == i2); //false System.out.println(i1 == i3); //false System.out.println(i3 == i4); //false System.out.println(i1.equals(i2)); //true System.out.println(i1.equals(i3)); //true System.out.println(i3.equals(i4)); //true }Copy the code

The result of the fifth line of code has been changed. First, we need to make it clear that lines 1 and 2 actually implement the auto-boxing process, which automatically implements the Integer. ValueOf method. Second, == compares addresses and equals compares values (eauals is overwritten here, so they compare specific values). So there’s no doubt about the last five lines of code. Since == compares addresses, why line 5 of example 1 is true requires an understanding of the caching mechanism for wrapped classes.

If we look at the source of the Integer class, we can see that there is a private static inner class on line 780, 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() {} }Copy the code

As we know, static inner classes are loaded when the whole Integer is loaded. The above code initializes an array of type Integer called cache in the range [-128, 127]. The caching mechanism is used to instantiate the wrapper object of the corresponding range value in advance. Whenever an object is created in the cache range, the instantiated object is used. This avoids creating multiple identical wrapper objects repeatedly and improves efficiency. If the range of objects we are using is within [-128, 127], we go directly to the static section to find the corresponding object. If the range of objects we are using is beyond this range, we will create a new Integer object.

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

So in example 1, i1 and i2 are 100, and the value range is [-128, 127], so the direct and static area search, so i1 and i2 point to the same address, so i1==i2; In example 2, i1 and i2 are 200, and the values are not in the range of [-128, 127], so a new object is created and placed in the heap, each pointing to a different address, so the address is different, i1 is not i2.

By analyzing the source code, we can see that only double and float autoboxing code does not use caching, each time new new object, the other six basic types use caching strategy. The caching policy is used because the cached objects are frequently used (such as characters, numbers between -128 and 127), preventing the creation of an instance of an object with each automatic boxing.

5. The difference between wrapper classes and primitive data types

  • Different defaults

The default value of the wrapper class is NULL, and the corresponding default value of the base data type (for example, 0 for integer and 0.0 for floating point)

  • Different storage areas

While basic data types store values in stack memory, wrapped classes put objects in the heap and call them by reference to them

  • Different ways of delivery

The primitive data type variable space stores values and passes values, one changes, the other doesn’t change, while the wrapper class is a reference data type. The variable space stores addresses (references) and passes references, one changes, the other changes.

Five, the summary

Above is my personal understanding of Java wrapper class as, in fact, learning these tools there is a better way of learning, is to see the official document (API official documentation address: docs.oracle.com/javase/8/do…


Finally, recently, many friends asked me for Linux learning roadmap, so I stayed up for a month in my spare time according to my own experience, and sorted out an e-book. Whether you are interviewing or self-improvement, I believe will help you! The directory is as follows:

Free to everyone, just ask everyone to point to me!

Ebook | Linux development learning roadmap

Also hope to have a small partner can join me, do this e-book more perfect!

Have a harvest? Hope the old iron people come to a triple whammy, give more people to see this article

Recommended reading:

  • Dry goods | programmers advanced architect necessary resources free of charge
  • Artifact | support resource site search