A wrapper class

1. Why is the wrapper class needed?

Java was designed with a basic principle: everything is an object, and all operations need to be described in object form. But there is a paradox here. The basic data type is not an object. So how do we fix this BUG? The simplest way to do this is to store the base data type as a class property, which is equivalent to wrapping the base data type.

A wrapper class that implements the basic data types

package com.shxt.demo01;

public class Int {/ / class
    private int number;// Basic data type
    
    public Int(int number){// Provide a constructor for a parameter, passing in the basic data type
        this.number = number;
    }
    
    public int intValue(a){// Get the data in the wrapper class
        return this.number;
    }
    
    // Other methods can be provided
}
Copy the code
package com.shxt.demo01;

public class MyTest {
    public static void main(String[] args) {
        Int temp = new Int(100);    // Wrap the basic data type into a class
        int result = temp.intValue();       // Get the basic data type from the classSystem.out.println(result+result); }}Copy the code

Code analysis:

We have implemented the way in which primitive data types are converted to Java objects, and Java provides us with similar implementation classes

Package form

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

Int ->Integer,char->Character, char->Character, char->Character

However, the packaging category given above can be divided into two types:

  • Object wrapper classes: Character, Boolean.
  • Numeric wrapper classes (direct subclasses of Number) : Byte, Short, Integer, Float, Double, Long.

Number is an abstract class that defines six operation methods: intValue(), shortValue(), byteValue(), floatValue(), longValue(), doubleValue().

2. Packing and unpacking

Now that there are primitive data types and wrapper classes, the conversion between these two variables is defined in the following way.

  • Boxing operation: Changes the base data type into the form of a wrapper class.
    • Each wrapper class constructor can accept variables of its own data type.
  • Unpacking operation: take out the packaged data from the packaged class.
    • Do this using a series of: xxxValue() methods provided in the Number class.

Example 1- Use int and Integer as examples to illustrate the process of packing and unpacking operations

public class Demo01 {
    public static void main(String args[]) {
        Integer obj = new Integer(10);  // Box the basic data types
        int temp = obj.intValue();  	// Unpack the basic data types
        System.out.println(temp * 2);  // The result is 20}}Copy the code

Instead of using the Int class I wrote, I’m using the Integer system class.

Example 2- Use a double and a double to illustrate the process of boxing and unboxing

public class Demo02 {
    public static void main(String args[]) {
        Double obj = new Double(10.2);  	// Box the basic data types
        double temp = obj.double Value(a);  	// Unpack the basic data types
        System.out.println(temp * 2);  		// The result is 20.4}}Copy the code

Example 3- Demonstrates the process of boxing and unboxing using Boolean and Boolean as examples (not the Number subclass)

public class Demo03 {
    public static void main(String args[]) {
        Boolean obj = new Boolean(false);  	// Box the basic data types
        boolean temp = obj.booleanValue();  // Unpack the basic data types
        System.out.println(temp);  			// The result is false}}Copy the code

You can now see that all wrapper classes operate using the same form of method. Prior to JDK1.5, all operations were in the above form of code, but after JDK1.5, Java provided automatic boxing and automatic unboxing for ease of development, and can directly use the objects of the wrapper class to perform mathematical calculations.

Example 4- Observe the automatic packing and unpacking operations using INT and Integer as examples

public class Demo04 {
    public static void main(String args[]) {
        Integer obj = 10;  	// Automatic boxing int->Integer
        int temp = obj;  	// Automatic unboxing Integer->int actually calls obj.intValue()
        obj ++;
        System.out.println(temp * obj);  // The result is 110}}Copy the code

Example 5- Observe the process of automatic boxing and automatic unboxing using Boolean and Boolean as examples (not the Number subclass)

public class Demo05 {
    public static void main(String args[]) {
        Boolean obj = false;  	// Automatic boxing Boolean ->Boolean
        boolean flag = obj;  	Boolean-> Boolean
      	if(! flag){ System.out.println(Boolean is not a subclass of Number); }}}Copy the code

Since Java provides automatic boxing and unboxing, Object can accept all data types.

Conversion process: Basic data types → automatic boxing (to become objects) → upward transformation to Object.

Example 6- Receiving the int data type as Object demonstrates the conversion process

public class Demo06 {
    public static void main(String args[]) {
        Object obj = 10;  	// int->Integer(automatically boxing as an Object)->Object
        int temp = (Integer)obj;  	// Object->Integer(cast to wrapper class)-> Automatic unboxing
        obj ++;
        System.out.println(temp * obj);  // The result is 110}}Copy the code

NullPointException for “no reason”

During our development, we encountered a number of NullPointExceptions caused by request parameters or interface definition fields being set to int (or some other primitive type). The code runs roughly as follows, but not exactly as this.

public class Demo06 {
    public static void main(String args[]) {
       Integer a = null;

		int b = a; // Throw NullPointException a.intValue();}}Copy the code

Code analysis:

The above code compiles, but throws a NullPointException.

Int b = a int b = a.int value ()

Since a’s reference value is NULL, calling a method on an empty object throws a NullPointException.

3. = = and equlas ()

You should know the difference between the two,

Equlas () compares values. Values of the same basic type refer to the same block of memory, so they can be compared with ==. Reference types do not.

public class Demo07 {
    public static void main(String args[]) {
        Integer obja = 10;  // Assign directly
        Integer objb = 10;	// Assign directly
        Integer objc = new Integer(10);  	// constructor
        System.out.println(obja == objb); 	// true does not compare memory addresses. Why is that?
        System.out.println(obja == objc);	// false
        System.out.println(objb == objc);	// false
        System.out.println(obja.equals(objc));	// true}}Copy the code

Code analysis:

Isn’t obja == objb supposed to compare memory addresses? Why is it equal? We need to solve this problem, source code analysis

This is rarely done using constructors when using wrapped classes, and is almost always done directly (as with strings), but remember to use equals() whenever content is equal.

Two wrapper classes reference equality

In Java, the “==” symbol determines the equivalence of a memory address. Specifically, primitive types determine whether values are equal, and reference types determine whether the address they point to is equal. Take a look at the following code, two similar code logic, but get completely different results.

public class Demo08 {
    public static void main(String args[]) {
      Integer a1 = 127;
      Integer a2 = 127;
      System.out.println(a1 == a2); // true

      Integer b1 = 128;
      Integer b2 = 128;
      System.out.println(b1 == b2); // false}}Copy the code

The answer to this must be found in the source code. The source code for the valueOf() method in the Integer class is as follows:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high) // Check whether the argument is in the cacheable range. Default is [-128, 127].
        return IntegerCache.cache[i + (-IntegerCache.low)]; // If so, fetch the initialized Integer object
   	return new Integer(i); // If not, a new Integer object is created
}
Copy the code

Code analysis:

Because 127 is in the range of [-128, 127], valueOf() will fetch the same Integer object every time, so the first “==” evaluates to true. 128 does not belong to [-128, 127], so valueOf() creates a new Integer object each time. Because the addresses of the two newly created objects are different, the result of the first “==” is false.

Analyze the comparison process again

package com.shxt.demo01;

public class MyTest {
    public static void main(String[] args) {
        Integer a = 1;
        Integer b = 2;
        Integer c = 3;
        Integer d = 3;
        Integer e = 321;
        Integer f = 321;
        Long g = 3L;
        Long h = 2L;

        System.out.println(c==d); // Cache mechanism, return true
        System.out.println(e==f); // The cache mechanism is exceeded and the return value is false
      	// (a+b) calculates that the automatic unpacking becomes an int, and c requires the automatic unpacking to become an int
        System.out.println(c==(a+b));
        //(a+b) evaluates automatic unboxing to int because equals compares content (a+b) with automatic boxing and returns true
      	System.out.println(c.equals(a+b));
      	// (a+b) evaluates to int, g to long, and (a+b) returns true
        System.out.println(g==(a+b));
      	//(a+b) calculates auto unboxing to int because equals compares content (a+b) to auto unboxing Integer
      	// Compare Long with Integer, return false
        System.out.println(g.equals(a+b));
      	Return true for automatic type conversionSystem.out.println(g.equals(a+h)); }}Copy the code

4. Data type conversion (core)

The most common use of the wrapper class is actually its data type conversion function, in the wrapper class, the biggest advantage is to provide String data into the basic data type method, using several representative classes to illustrate:

  • Integer class :public static int parseInt(String s)
  • Public static Double parseDouble(String s)
  • Public static Boolean parseBoolean(String s).

The **Character class does not have a method that converts a String to a Character, because the String class has a charAt() method that fetches the Character content by index, and a Character is only one bit long.

Example 1: Turn a string into an int

public class Demo01 {
    public static void main(String args[]) {
        String str = "123";  / / string
        int temp = Integer.parseInt(str);//String->int
        System.out.println(temp * 2); }}Copy the code

At this point, the string becomes a primitive data type. However, it is important to note that the string to be converted to a number must consist of numbers. If it is not a number, a NumberFormatException is raised during conversion

Example 2: Error code

public class Demo02 {
    public static void main(String args[]) {
        String str = "1sss3";  / / string
        int temp = Integer.parseInt(str);
        System.out.println(temp * 2); }}Copy the code
Exception in thread "main" java.lang.NumberFormatException:For input string:"1sss3"
Copy the code

Example 3: Turn a string into a double

public class Demo03 {
    public static void main(String args[]) {
        String str = "13";  / / string
        double temp = Double.parseDouble(str);
        System.out.println(temp * 2); // Output 26.0}}Copy the code

Example 4: Change a string to Boolean data

public class Demo04 {
    public static void main(String args[]) {
        String str = "true";  / / string
        boolean flag = Boolean.parseBoolean(str);
        if(flag) {
            System.out.println("Satisfied!"); 
        } else {
            System.out.println("Condition not met!"); }}}// Console output: the condition is met
Copy the code

Example 5: Change a string to Boolean data

public class Demo05 {
    public static void main(String args[]) {
        String str = "hanpang";  // Error string
        boolean flag = Boolean.parseBoolean(str);
        if(flag) {
            System.out.println("Satisfied!");
        } else {
            System.out.println("Condition not met!"); }}}// Console output: does not meet the condition!
Copy the code

Code analysis:

When Boolean is converted, if the string to be converted is not true or false, it is treated as false.

Now that we have implemented a string to primitive, we must be able to implement a string to primitive. There are two ways to do this:

  • Operation 1: Any basic data type and string is indicated as a string after the + operation is used.

    public class Demo06 {
        public static void main(String args[]) {
            int num = 100;
            String str = num + "";  / / into a String
            System.out.println(str.replaceAll("0"."9")); }}// Console output: 199
    Copy the code

    Although such operations can be easily completed, there will be garbage problems.

  • Public static String valueOf public static String valueOf

    public class Demo07 {
        public static void main(String args[]) {
            int num = 100;
            String str = String.valueOf(num);  / / into a String
            System.out.println(str.replaceAll("0"."9")); }}Copy the code

    Such transformations do not generate garbage, so they are often used during development.

5. Summary

  • Make sure that JDK1.5 provides automatic packing and unpacking operations.
  • Conversions between strings and primitive data types:
    • The string becomes a primitive data type, depending on the parseXxx() method of the wrapper class.
    • The base data type becomes a String, using the string.valueof (data type variable) method.