Validation in Java constructors

Damian Kolasa
3 min readMay 31, 2018

--

Photo by Nick Tiemeyer on Unsplash

When writing Java classes I always looked with a bit of uneasiness at the code that did some validation in the constructor body.

Constructor validation

Don’t get me wrong I love the idea of having “always valid” classes inside my system. And holding this invariant is far better than having a dedicated validate() method.

Dedicated validation method

But I felt like it’s not the way to do this, and besides mere aesthetics, I couldn’t find anything to convince others not to do this. Is there a reasonable and concrete argument against doing validation in constructors?

Java is a statically typed language that gets compiled to bytecode (it’s called bytecode because there is a single byte used to convey operations to be executed by VM) that is then executed by a Java Virtual Machine. Statically typed, means that during compile time, and at runtime, there are performed some checks to make sure our code runs smoothly. So we can be pretty certain that nothing bad will sneak through, and basically what will compile will work well. With that in mind, there is no problem for me to declare an exception throwing constructor. So what’s all the fuss about?

It’s not about what we write it’s about what is being executed by JVM. Bytecode generated for piece of code from first listing looks like this:

Bytecode for code from first listing.

Wait, what? Yup, single “operation” is deconstructed into three separate instructions (new, dup, invokespecial) from which only the last one actually invokes the code inside a constructor body.

Let’s talk briefly about those three opcodes (operation codes):

  • new [offset 0:] allocates memory needed by our new shiny object.
  • dup [offset 3:] creates a duplicate of top-level stack value (Java has a stack-based execution model, without any additional registers and so on).
  • invokespecial [offset 18:] instruction which calls a <init> method (which is our constructor).

All this work, especially memory allocation just to know that passed arguments are invalid, and given object cannot be constructed. But why should I care about some unnecessary object creation ?

As you may know, new objects are allocated inside Eden Space (special area of memory managed by JVM), which is subject to Garbage Collection like every other part of JVM managed memory. More unnecessary object allocation occurs then more Eden space will be used up, and more minor GC occurrences we will have. As far as GC is needed it’s not desired. It’s like a family friend, your happy that he visits, but you would really like to use toilet alone.

So as you can see, things get a little bit different when you look under the hood. Java abstracted away object creation in high-level instructions, which gave us permission for certain assumptions which do not hold even a single level of abstraction below.

Public static factory method example

I recommend using public static factory methods for such objects (as described in Effective Java Chapter 2. Item 1.). Those allow you to perform validation without any memory and CPU time wasted, plus allows you to hide actual method of creating an instance of given type. You may cache it, pool it, extend it or whatever. Just another level of indirection, that gives you some room for later growth and change.

Thank you for your time. If you have questions you can reach me on twitter. Please clap if you liked it.

--

--

Damian Kolasa

Passionate Java developer with 14yr experience. Loves programming, interested in writing software that lasts. https://howtodesignsystems.it/