raju raju - 3 months ago 9
Java Question

Why do we prefer primitives to boxed primitives in 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?

Answer

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.