Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we prefer primitives to boxed primitives in java

Tags:

java

I was reading effective java 2nd edition and page number 23 says

// Hideously slow program! Can you spot the object creation
public static void main(String[] args) {
    Long sum = 0L;
    for(long i=0; i<=Integer.MAX_VALUE; i++){
        sum += i;
    }
    System.out.println(sum)
}

Author says that the above code generates 2^31 object instantiations unnecessarily. Why does sum += i generate new Object? if I change the statement to

sum = sum + 1

not have this side effect?

like image 803
raju Avatar asked Aug 17 '16 18:08

raju


People also ask

Why does Java have boxed types?

Generally when you work with collections, you're dealing with arrays of Objects. In languages like Java, there is a difference between a primitive and an Object. When a primitive is "boxed", it's essentially just a wrapper around a primitive so it plays nice with the rest of the framework that's expecting an Object.

What is boxed primitive in Java?

In Java, when primitive values are boxed into a wrapper object, certain values (any boolean, any byte, any char from 0 to 127, and any short or int between -128 and 127) are interned, and any two boxing conversions of one of these values are guaranteed to result in the same object.

Why Java still use primitive types?

Objects are much more heavyweight than primitive types, so primitive types are much more efficient than instances of wrapper classes. Primitive types are very simple: for example an int is 32 bits and takes up exactly 32 bits in memory, and can be manipulated directly.

Should I use primitive or wrapper?

Verdict. Generally, choose primitive types over wrapper classes unless using a wrapper class is necessary. Primitive Types will never be slower than Wrapper Objects, however Wrapper Objects have the advantage of being able to be null.

What are boxed primitives in Java?

Each of the primitive types in Java also has an equivalent reference type. For example, int has Integer, long has Long, boolean has Boolean, and so on. These reference types are called Boxed primitives. As it only supports values.

How many types of primitive types are there in Java?

There are 8 primitive types: Reference types are references to objects. All reference types are a subclass of type java.lang.Object Following are 5 Java reference types. Each of the primitive types in Java also has an equivalent reference type. For example, int has Integer, long has Long, boolean has Boolean, and so on.

What is the difference between primitive types and integers?

Primitive types are very simple: for example an int is 32 bits and takes up exactly 32 bits in memory, and can be manipulated directly. An Integer object is a complete object, which (like any object) has to be stored on the heap, and can only be accessed via a reference (pointer) to it.

What are primitive Boolean variables in Java?

Java boolean variables (the primitive ones) allow only two possible values: true or false, the last one as default. We use booleans to represent values that only can represent a true or a false statement, such as:


4 Answers

Trying to rephrase what others have said in a clearer way:

The problem with sum is that Long is a reference type; in other words, it is some sort of Object. Objects live on the heap; they are created (using "new" and a constructor) by the JVM, and "managed" by the garbage collector.

The auto-boxing feature allows you to use that reference-type Long variable the same way you would use a primitive-type long variable.

But a Long object is immutable; once created, its value can never change. But the whole loop is about constantly changing a value (by incrementing the counter)! So, to increment the counter, you have to fetch the value of the "current" Long object; add 1; and stuff that into the next Long object. Again, and again, ...

So, what your program is doing here is: creating garbage all the time. In other words: those Long objects are created; used once (to retrieve their value); and then they are "forgotten" (because no reference to them is kept anywhere). So they are immediately eligible for garbage collection.

Meaning: there are actually two impacts on performance here:

  1. Unnecessary object creation [which is pretty cheap in Java, but still "more expensive" than simple calculations on a long value; the later probably being just one, two CPU instructions; whereas Object creation will lead to memory access and quite some CPU operations! ]
  2. High-speed creation of objects that need to be garbage collected.
like image 177
GhostCat Avatar answered Sep 22 '22 10:09

GhostCat


Due to autoboxing as your variable sum is not a primitive type but of type Long (the wrapper class), sum += i will behind the scene create a new Long instance as it is an immutable class so it will somehow be equivalent to sum = new Long(sum.longValue() + 1)

like image 29
Nicolas Filotto Avatar answered Sep 23 '22 10:09

Nicolas Filotto


sum = sum + 1 will still have same problem as sum += 1 because sum on the right unboxes the value, then adds 1 to it, and finally creates a new Long object in order to box the result and assign the sum reference variable to point to the newly created object.

like image 35
Code-Apprentice Avatar answered Sep 19 '22 10:09

Code-Apprentice


This happens because the java.lang.Long class is immutable. In other words, a new Long is created in each iteration of the loop instead of mutating the original in place. Compared to a primitive long, the boxed Long carries a lot of baggage. Your alternative statement, sum = sum + 1 would have the same effect as the original code. Redeclaring sum as long sum = 0L; would instead create a new long on each iteration, which is substantially cheaper to create than a Long.

like image 42
Hoagy Carmichael Avatar answered Sep 22 '22 10:09

Hoagy Carmichael