loading...

Effective Java Tuesday! Avoid Creating Unnecessary Objects!

kylec32 profile image Kyle Carter ・3 min read

Effective Java Review (36 Part Series)

1) Effective Java Tuesday! Let's Consider Static Factory Methods 2) Effective Java Tuesday! The Builder Pattern! 3 ... 34 3) Effective Java Tuesday! Singletons! 4) Effective Java Tuesday! Utility Classes! 5) Effective Java Tuesday! Prefer Dependency Injection! 6) Effective Java Tuesday! Avoid Creating Unnecessary Objects! 7) Effective Java Tuesday! Don't Leak Object References! 8) Effective Java Tuesday! Avoid Finalizers and Cleaners! 9) Effective Java Tuesday! Prefer try-with-resources 10) Effective Java Tuesday! Obey the `equals` contract 11) Effective Java Tuesday! Obey the `hashCode` contract 12) Effective Java Tuesday! Override `toString` 13) Effective Java Tuesday! Override `clone` judiciously 14) Effective Java Tuesday! Consider Implementing `Comparable` 15) Effective Java Tuesday! Minimize the Accessibility of Classes and Member 16) Effective Java Tuesday! In Public Classes, Use Accessors, Not Public Fields 17) Effective Java Tuesday! Minimize Mutability 18) Effective Java Tuesday! Favor Composition Over Inheritance 19) Effective Java Tuesday! Design and Document Classes for Inheritance or Else Prohibit It. 20) Effective Java Tuesday! Prefer Interfaces to Abstract Classes 21) Effective Java! Design Interfaces for Posterity 22) Effective Java! Use Interfaces Only to Define Types 23) Effective Java! Prefer Class Hierarchies to Tagged Classes 24) Effective Java! Favor Static Members Classes over Non-Static 25) Effective Java! Limit Source Files to a Single Top-Level Class 26) Effective Java! Don't Use Raw Types 27) Effective Java! Elminate Unchecked Warnings 28) Effective Java! Prefer Lists to Array 29) Effective Java! Favor Generic Types 30) Effective Java! Favor Generic Methods 31) Effective Java! Use Bounded Wildcards to Increase API Flexibility 32) Effective Java! Combine Generics and Varargs Judiciously 33) Effective Java! Consider Typesafe Hetergenous Containers 34) Effective Java! Use Enums Instead of int Constants 35) Effective Java! Use Instance Fields Instead of Ordinals 36) Effective Java! Use EnumSet Instead of Bit Fields

Today we are onto our sixth item from Effective Java. This one's title particularly makes me smile. Avoid creating unnecessary objects. What's more uncontroversial than saying, "Don't do things you don't need to do." We are all looking for shortcuts of how to get a job done more quickly so this one we automatically get for free right? Well not quite, there is actually a little bit more to be said here than, "Be lazy." So let's get started.

So why would someone do something that they don't need to do? Well we will go over some of the ways this can happen throughout this post but I would sum up most of these cases simply as the following, ignorance and lack of attention. This is understandable. Sometimes we just don't realize the damage we may be doing or we do know to avoid something but may not realize we are doing that thing.

Let's start off with the first example from the book:

String title = new String("Effective Java");

So what does this do? Well it does exactly what it looks like it will do, it creates a new String for each time it is called. But that's not what we actually want to do. This simply creates more objects for the garbage collector to clean up without any benefit. Compare that to the more efficient way to accomplish this which also turns out to be cleaner:

String title = "Effective Java";

In this case no extra objects will be created no matter how many times this line is run. Also because of String interning if this same static string shows up multiple times in the JVM it will only be allocated once which is a fun memory saving tip.

So why would someone do the first example? Good question. My guess would be simply not knowing that it has a negative effect.

So what are some ways that we can help avoid creating unnecessary objects. Well it's no wonder that the book starts with talking about static factory methods as it comes up as a solution again. As mentioned in that article, by using a static factory method we can make the determination if we want to create a new object or not whereas with a constructor we are forced to create a new object every time. An example of this can be seen with the Boolean object:

Boolean trueBoolean = new Boolean("true");
// vs
Boolean falseBoolean = Boolean.parseValue("false");

Let's look at another example of a place where developers sometimes get themselves into issues with creating unnecessary objects. This time it's boxed types. Let's look at the example from the book:

private static long sum() {
  Long sum = 0L;
  for (int i = 0; i< Integer.MAX_VALUE; i++) {
    sum += i; 
  }
  return sum;
}

The one capital L makes this code much less efficient where we are boxing and unboxing values over and over, creating more and more objects for not reason. Those that I work with know that I'm not a huge fan of boxed types. I see people accidentally using them for no good reason and they can have subtle effects that people don't realize.

So in these previous examples we have seen creating unnecessary small objects. While this should still be avoided it would take looping over this mistake many times before it actually started to affect our performance. What are some other times that we should particularly be concerned about creating unnecessary objects? Well even if we only create a few unnecessary objects if we are creating expensive objects unnecessarily it can make a difference so we need to be particularly careful with these expensive objects. The most common example of this is database connection pools. I won't personally go into this as I think the logic is simple to follow however I did want to mention it as something to take care of.

So there you have it, don't create objects for no good reason. This doesn't mean there aren't good reasons. Later in the book we will discuss defensive copying and keeping the code clear is worth a few extra object creations if it comes to that.

So the core lesson I'm trying to share with this post is to be careful with your allocations. Realize what your code is doing and that should help improve the performance of your application.

Effective Java Review (36 Part Series)

1) Effective Java Tuesday! Let's Consider Static Factory Methods 2) Effective Java Tuesday! The Builder Pattern! 3 ... 34 3) Effective Java Tuesday! Singletons! 4) Effective Java Tuesday! Utility Classes! 5) Effective Java Tuesday! Prefer Dependency Injection! 6) Effective Java Tuesday! Avoid Creating Unnecessary Objects! 7) Effective Java Tuesday! Don't Leak Object References! 8) Effective Java Tuesday! Avoid Finalizers and Cleaners! 9) Effective Java Tuesday! Prefer try-with-resources 10) Effective Java Tuesday! Obey the `equals` contract 11) Effective Java Tuesday! Obey the `hashCode` contract 12) Effective Java Tuesday! Override `toString` 13) Effective Java Tuesday! Override `clone` judiciously 14) Effective Java Tuesday! Consider Implementing `Comparable` 15) Effective Java Tuesday! Minimize the Accessibility of Classes and Member 16) Effective Java Tuesday! In Public Classes, Use Accessors, Not Public Fields 17) Effective Java Tuesday! Minimize Mutability 18) Effective Java Tuesday! Favor Composition Over Inheritance 19) Effective Java Tuesday! Design and Document Classes for Inheritance or Else Prohibit It. 20) Effective Java Tuesday! Prefer Interfaces to Abstract Classes 21) Effective Java! Design Interfaces for Posterity 22) Effective Java! Use Interfaces Only to Define Types 23) Effective Java! Prefer Class Hierarchies to Tagged Classes 24) Effective Java! Favor Static Members Classes over Non-Static 25) Effective Java! Limit Source Files to a Single Top-Level Class 26) Effective Java! Don't Use Raw Types 27) Effective Java! Elminate Unchecked Warnings 28) Effective Java! Prefer Lists to Array 29) Effective Java! Favor Generic Types 30) Effective Java! Favor Generic Methods 31) Effective Java! Use Bounded Wildcards to Increase API Flexibility 32) Effective Java! Combine Generics and Varargs Judiciously 33) Effective Java! Consider Typesafe Hetergenous Containers 34) Effective Java! Use Enums Instead of int Constants 35) Effective Java! Use Instance Fields Instead of Ordinals 36) Effective Java! Use EnumSet Instead of Bit Fields

Posted on by:

kylec32 profile

Kyle Carter

@kylec32

Backend Architect at MasterControl

Discussion

markdown guide
 

The Boolean example is IMO not the best example for a factory method. As Boolean provides the two boolean values as immutable constants which are easier to use.

Also the parseBoolean (not parseValue) method returns a native boolean, which needs to be boxed. This is usually done via the Boolean#valueOf method, which will also return the constants.

You can see this quite nicely in the jshell:

Boolean.parseBoolean("true") == Boolean.TRUE
 

As I have written in another reply, in this case the boxing will not consume another 40 bytes, as only the reference to the Boolean.FALSE constant will be returned.