Why do we use autoboxing and unboxing in Java?
Asked Answered
T

10

97

Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes. For example, converting an int to an Integer, a double to a Double, and so on. If the conversion goes the other way, this is called unboxing.

So why do we need it and why do we use autoboxing and unboxing in Java?

Tetrachord answered 25/12, 2014 at 12:59 Comment(5)
Basically for Generics..Mornings
Integer have parseInt method. int does not have. :)Jellied
@VishalZanzrukia So just for getting more functionality?Tetrachord
You can have List<Integer>, but you can't have List<int>.Jellied
Yes..exactly..to get more functionalityJellied
O
192

Some context is required to fully understand the main reason behind this.

Primitives versus classes

Primitive variables in Java contain values (an integer, a double-precision floating point binary number, etc). Because these values may have different lengths, the variables containing them may also have different lengths (consider float versus double).

On the other hand, class variables contain references to instances. References are typically implemented as pointers (or something very similar to pointers) in many languages. These things typically have the same size, regardless of the sizes of the instances they refer to (Object, String, Integer, etc).

This property of class variables makes the references they contain interchangeable (to an extent). This allows us to do what we call substitution: broadly speaking, to use an instance of a particular type as an instance of another, related type (use a String as an Object, for example).

Primitive variables aren't interchangeable in the same way, neither with each other, nor with Object. The most obvious reason for this (but not the only reason) is their size difference. This makes primitive types inconvenient in this respect, but we still need them in the language (for reasons that mainly boil down to performance).

Generics and type erasure

Generic types are types with one or more type parameters (the exact number is called generic arity). For example, the generic type definition List<T> has a type parameter T, which can be Object (producing a concrete type List<Object>), String (List<String>), Integer (List<Integer>) and so on.

Generic types are a lot more complicated than non-generic ones. When they were introduced to Java (after its initial release), in order to avoid making radical changes to the JVM and possibly breaking compatibility with older binaries, the creators of Java decided to implement generic types in the least invasive way: all concrete types of List<T> are, in fact, compiled to (the binary equivalent of) List<Object> (for other types, the bound may be something other than Object, but you get the point). Generic arity and type parameter information are lost in this process, which is why we call it type erasure.

Putting the two together

Now the problem is the combination of the above realities: if List<T> becomes List<Object> in all cases, then T must always be a type that can be directly assigned to Object. Anything else can't be allowed. Since, as we said before, int, float and double aren't interchangeable with Object, there can't be a List<int>, List<float> or List<double> (unless a significantly more complicated implementation of generics existed in the JVM).

But Java offers types like Integer, Float and Double which wrap these primitives in class instances, making them effectively substitutable as Object, thus allowing generic types to indirectly work with the primitives as well (because you can have List<Integer>, List<Float>, List<Double> and so on).

The process of creating an Integer from an int, a Float from a float and so on, is called boxing. The reverse is called unboxing. Because having to box primitives every time you want to use them as Object is inconvenient, there are cases where the language does this automatically - that's called autoboxing.

Ogg answered 25/12, 2014 at 13:48 Comment(1)
As per your explanation we need these classes Integer, String, ... to implement generics. Is there any other reason?Flathead
Q
23

Auto Boxing is used to convert primitive data types to their wrapper class objects. Wrapper class provide a wide range of function to be performed on the primitive types. The most common example is :

int a = 56;
Integer i = a; // Auto Boxing

It is needed because of programmers easy to be able to directly write code and JVM will take care of the Boxing and Unboxing.

Auto Boxing also comes in handy when we are working with java.util.Collection types. When we want to create a Collection of primitive types we cannot directly create a Collection of a primitive type , we can create Collection only of Objects. For Example :

ArrayList<int> al = new ArrayList<int>(); // not supported 

ArrayList<Integer> al = new ArrayList<Integer>(); // supported 
al.add(45); //auto Boxing 

Wrapper Classes

Each of Java's 8 primitive type (byte,short,int,float,char,double,boolean,long) hava a seperate Wrapper class Associated with them. These Wrapper class have predefined methods for preforming useful operations on primitive data types.

Use of Wrapper Classes

String s = "45";
int a = Integer.parseInt(s); // sets the value of a to 45.

There are many useful functions that Wrapper classes provide. Check out the java docs here

Unboxing is opposite of Auto Boxing where we convert the wrapper class object back to its primitive type. This is done automatically by JVM so that we can use a the wrapper classes for certain operation and then convert them back to primitive types as primitives result int faster processing. For Example :

Integer s = 45;
int a = s; auto UnBoxing;

In case of Collections which work with objects only auto unboxing is used. Here's how :

ArrayList<Integer> al = new ArrayList<Integer>();
al.add(45);

int a = al.get(0); // returns the object of Integer . Automatically Unboxed . 
Quartas answered 25/12, 2014 at 13:41 Comment(0)
A
4

The primitive (non-object) types have there justification in efficiency.

The primitive types int, boolean, double are immediate data, whereas Objects are references. Hence fields (or variables)

int i;
double x;
Object s;

would need local memory 4+8+8? where for the object only the reference (address) to memory is stored.

Using the Object wrappers Integer, Double and others, one would introduce an indirection, reference to some Integer/Double instance in the heap memory.

Why boxing is needed?

That is a question of relative scope. In a future java it is planned to be able to have an ArrayList<int>, lifting primitive types.

Answer: For now an ArrayList only works for Object, reserving room for an object reference, and managing garbage collection likewise. Hence generic types are Object children. So if one wanted an ArrayList of floating point values, one needed to wrap a double in a Double object.

Here Java differs from the traditional C++ with its templates: C++ classes vector<string>, vector<int> would create two compilation products. Java design went for having one ArrayList.class, not needing for every parameter type a new compiled product.

So without boxing to Object one would need to compile classes for every occurrence of a parameter type. In concreto: every collection or container class would need a version for Object, int, double, boolean. The version for Object would handle all child classes.

In fact, the need for such diversification already existed in Java SE for IntBuffer, CharBuffer, DoubleBuffer, ... which operate on int, char, double. It was solved in a hacky way by generating these sources from a common one.

Azoth answered 25/12, 2014 at 14:17 Comment(0)
B
4

Starting with JDK 5, java has added two important functions: autoboxing and autounboxing. AutoBoxing is the process for which a primitive type is automatically encapsulated in the equivalent wrapper whenever such an object is needed. You do not have to explicitly construct an object. Auto-unboxing is the process whereby the value of an encapsulated object is automatically extracted from a type wrapper when its value is required. You do not need to call a method such as intValue() or doubleValue().

The addition of autoboxing and auto-unboxing greatly simplifies writing algorithms, eliminating the bait manually boxing and unboxing of values. It is also helpful to avoid mistakes. It is also very important for generics, who only operate on objects. Lastly, autoboxing facilitates work with the Collections Framework.

Baur answered 2/7, 2017 at 20:42 Comment(0)
E
2

Some data structures can accept only objects, no primitive types.

Example: the key in a HashMap.

See this question for more: HashMap and int as key

There are other good reasons, such as a "int" field in a database, which could be NULL as well. An int in Java cannot be null ; an Integer reference can. Autoboxing and unboxing provide with a facility to avoid writing extraneous code in the conversions back and forth.

Eartha answered 25/12, 2014 at 13:4 Comment(0)
M
2

why do we have (un)boxing?

to make writing code where we mix primitives and their Object Oriented (OO) alternatives more comfortable/less verbose.

why do we have primitives and their OO alternatives?

primitive types are not classes (unlike in C#), thus they are not subclasses of Object and can not be overridden.

we have primitives like int for performance reasons, and the Object alternatives like Integer for the benefits of OO programming, and as a minor point, to have a good location for utility constants and methods (Integer.MAX_VALUE and Integer.toString(int)).

The OO benefits are visible most easily with Generics (List<Integer>), but are not limited to that, for example:

Number getMeSome(boolean wantInt) {

    if (wantInt) {
        return Integer.MAX_VALUE;
    } else {
        return Long.MAX_VALUE;
    }
}
Meditation answered 25/12, 2014 at 13:33 Comment(0)
M
1

ArrayList does not support primitive types only support class. but we need to use primitive types e.g int, double etc.

ArrayList<String> strArrayList = new ArrayList<String>(); // is accepted.

ArrayList<int> intArrayList = new ArrayList<int>(); // not accepted.

The Integer class wraps a value of the primitive type int in an object.so bellow code is accepted.

ArrayList<Integer> intArrayList = new ArrayList<Integer>(); // is accepted.

we can add a value with add(value) method. To add a String value say "Hello" in strArrayList code is just

strArrayList.add("Hello");  

and add a int value say 54 we can write

intArrayList.add(54);

but when we write intArrayList.add(54); compiler convert to the following line

intArrayList.add(Integer.valueOf(54)); 

As intArrayList.add(54) is easy and more acceptable from user side so compiler does the hard job which is `intArrayList.add(Integer.valueOf(54)); it is autoBoxing.

Similarly to retrieve value we just type intArrayList.get(0) and compiler convert to <code>intArrayList.get(0).intValue(); which is autoUnboxing.

Miscreated answered 18/1, 2019 at 11:49 Comment(0)
S
0

Because they are different types, and as a convenience. Performance is likely the reason for having primitive types.

Sphenoid answered 25/12, 2014 at 13:3 Comment(0)
R
0

Autoboxing: Converting a primitive value into an object of the corresponding wrapper class.

Unboxing: Converting an object of a wrapper type to its corresponding primitive value

// Java program to illustrate the concept 
// of Autoboxing and Unboxing 
import java.io.*; 

class GFG 
{ 
    public static void main (String[] args) 
    { 
        // creating an Integer Object 
        // with value 10. 
        Integer i = new Integer(10); 

        // unboxing the Object 
        int i1 = i; 

        System.out.println("Value of i: " + i); 
        System.out.println("Value of i1: " + i1); 

        //Autoboxing of char 
        Character gfg = 'a'; 

        // Auto-unboxing of Character 
        char ch = gfg; 
        System.out.println("Value of ch: " + ch); 
        System.out.println("Value of gfg: " + gfg); 

    } 
} 
Redbud answered 19/1, 2019 at 6:23 Comment(0)
P
0

Another Special Case is,

Integer intval = null;
int toPrimitive = intval;
System.out.println(toPrimitive);

We are getting NullPointerException for above scenario. that means we can catch NPE

Posterior answered 4/10, 2021 at 20:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.