JavaRush /Java Blog /Random EN /Wrapping, unwrapping and packing

Wrapping, unwrapping and packing

Published in the Random EN group
Hello! You are already quite familiar with primitive types, and have worked with them a lot. Wrapping, unwrapping and packing - 1Primitives in programming, and in Java in particular, have many advantages: they take up little memory, thereby increasing the efficiency of the program, and are clearly divided into ranges of values. However, in the process of learning Java, we have repeated more than once, like a mantra, “ in Java everything is an object .” But primitives are a direct refutation of these words. They are not objects. So the principle “everything is an object” is false? Not really. In Java, every primitive type has its twin brother, the wrapper class ( Wrapper). What is a wrapper? A wrapper is a special class that stores the value of a primitive inside itself. But since this is a class, it can create its own instances. They will store the necessary primitive values ​​inside, while being real objects. The names of the wrapper classes are very similar to the names of the corresponding primitives, or completely coincide with them. Therefore, it will be very easy to remember them.
Wrapper Classes for Primitive Data Types
Primitive Data Types Wrapper Classes
int Integer
short Short
long Long
byte Byte
float Float
double Double
char Character
boolean Boolean
Wrapper class objects are created just like any other:

public static void main(String[] args) {

   Integer i = new Integer(682);
  
   Double d = new Double(2.33);
  
   Boolean b = new Boolean(false);
}
Wrapper classes allow you to mitigate the disadvantages that primitive types have. The most obvious one is that primitives do not have methods . For example, they don't have a method toString(), so you can't, for example, convert a number intto a string. But with a wrapper class Integerit’s easy.

public static void main(String[] args) {

   Integer i = new Integer(432);
  
   String s = i.toString();
}
There will also be difficulties with the reverse transformation. Let's say we have a string that we know for sure contains a number. However, in the case of a primitive type, intwe will not be able to get this number from the string and turn it, in fact, into a number. But thanks to wrapper classes, we now have this opportunity.

public static void main(String[] args) {

   String s = "1166628";

   Integer i = Integer.parseInt(s);

   System.out.println(i);
}
Output: 1166628 We have successfully retrieved a number from a string and assigned it to a reference variable Integer i. By the way, about links. You already know that parameters are passed to methods in different ways: primitives are passed by value, and objects are passed by reference. You can use this knowledge when creating your methods: if your method works, for example, with fractional numbers, but you need the logic of passing by reference, you can pass parameters to the method Double/Floatinstead of double/float. In addition, in addition to methods, wrapper classes have static fields that are very convenient to use. For example, imagine that you are now faced with a task: print the maximum possible number to the console int, and then the minimum possible number. The task seems to be elementary, but still, you’ll hardly be able to do it without Google. And wrapper classes easily allow you to solve the following “everyday problems”:

public class Main {
   public static void main(String[] args) {

       System.out.println(Integer.MAX_VALUE);
       System.out.println(Integer.MIN_VALUE);
   }
}
Such fields allow you not to be distracted from more serious tasks. Not to mention the fact that in the process of printing the number 2147483647 (this is exactly MAX_VALUE) it is not surprising to mistype it :) In addition, in one of the previous lectures we already drew attention to the fact that objects of wrapper classes are immutable (Immutable) .

public static void main(String[] args) {

   Integer a = new Integer(0);
   Integer b = new Integer(0);

   b = a;
   a = 1;
   System.out.println(b);
}
Output: 0 The object that the reference originally pointed to аhas not changed its state, otherwise the value bwould have changed too. As with String, instead of changing the state of the wrapper object, an entirely new object is created in memory. Why did the creators of Java ultimately decide to keep primitive types in the language? Since everything should be an object, and we already have wrapper classes that can be used to express everything that primitives express, why not just leave them in the language and remove the primitives? The answer is simple - performance. Primitive types are called primitive because they are devoid of many “heavy” features of objects. Yes, an object has many convenient methods, but you don’t always need them. Sometimes you just need the number 33, or 2.62, or the value of true/ false. In situations where all the benefits of objects are not important and are not needed for the program to work, primitives will do a much better job.

Auto-packing/auto-unpacking

One of the features of primitives and their wrapper classes in Java is autoboxing/autounboxing. Wrapping, unwrapping and packing - 2 Let's understand this concept. As you and I already learned earlier, Java is an object-oriented language. This means that all programs written in Java are made up of objects. Primitives are not objects. However, the wrapper class variable can be assigned a value of a primitive type. This process is called autoboxing . In the same way, a variable of a primitive type can be assigned an object of a wrapper class. This process is called autounboxing . For example:

public class Main {
   public static void main(String[] args) {
       int x = 7;
       Integer y = 111;
       x = y; // auto unpacking
       y = x * 123; // autopacking
   }
}
On line 5, we assign the primitive x the value of y, which is an object of the wrapper class Integer. As you can see, no additional actions are needed for this: the compiler knows that intand Integer, in fact, the same thing . This is auto-unpacking. The same thing happens with autoboxing in line 6: the object y is easily assigned the value of primitives (x*123). This is an example of autopacking. This is why the word “auto” is added: to assign primitive references to objects of their wrapper classes (and vice versa) you do not need to do anything, everything happens automatically . Convenient, right? :) Another very great convenience of auto-packing/auto-unpacking is manifested in the operation of the methods. The fact is that method parameters are also subject to autopacking and autounpacking . And, for example, if one of them takes two objects as input Integer, we can easily pass ordinary primitives there int!

public class Main {
   public static void main(String[] args) {

       printNumber(7);//regular int, even without a variable
   }

   public static void printNumber(Integer i) {
       System.out.println("You entered a number" + i);
   }
}
Output: You entered the number 7. It works the other way around:

public class Main {
   public static void main(String[] args) {

       printNumber(new Integer(632));
   }

   public static void printNumber(int i) {
       System.out.println("You entered a number" + i);
   }
}
An important point to remember: autoboxing and unboxing does not work for arrays !

public class Main {
   public static void main(String[] args) {

       int[] i = {1,2,3,4,5};
      
       printArray(i);//error, won't compile!
   }
  
   public static void printArray(Integer[] arr) {
       System.out.println(Arrays.toString(arr));
   }
}
Trying to pass an array of primitives to a method that takes an array of objects as input will cause a compilation error. Finally, let’s once again briefly compare primitives and wrappers Primitives:
  • have a performance advantage
Wrappers:
  • They allow you to not violate the principle “everything is an object”, so that numbers, symbols and boolean values ​​​​true/false do not fall out of this concept
  • Expand the ability to work with these values ​​by providing convenient methods and fields
  • Necessary when some method can work exclusively with objects
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION