The Controversy of var in Java

Reading Time: 6 minutes

What’s the big deal with var in Java? Should we be using var or can we ignore it? In my journey with var in Java, I’ll share what I’ve learnt works and doesn’t work for me.

var in Java | Introduction

Java 10 first introduced var as a reserved type name much like a long or int but it’s not a keyword. This ensures backward compatibility for programs using var as a function name or variable name.

It has a limited scope, meaning that it can only be used in local variable declarations. It basically exists to improve code readability by emphasizing cutting down on boiler plate code.  This is achieved by using local-variable type inference … sound familiar? More on that soon. Here are some basic examples of using var.

You can clearly see that we didn’t have to code the type on the left hand side of the variable declaration.

Local-variable type inference allows the ability for the Java compiler to identify the type of the local variable using the correct side of an expression. Don’t be fooled by “var” like in JavaScript which has dynamic capabilities. Java var is not dynamically evaluated, we still get good old Java compile type safety.

What’s the Big Deal with var in Java?

We already have a way to reduce some of this boilerplate code. Java 7 added type inference via the diamond operator to handle this for Collections.

As you can see, the Java 7 and Java 10 code examples just swap the type information from left for right. So which do you prefer?

The argument is that  it is easier to read your code when the type information is missing on the left when using var. Hmm .. I actually disagree. My eyes immediately want to know the type information as so I look to the right to take a mental note of it.

I much rather use diamond operator type inference when declaring my Collections. So far, I’m not sold on var in this context.

Coding to an Interface with var in Java

There is a subtle difference between relying on type inference with the diamond operator vs using var when it comes to coding to an Interface.  Coding to an interface is something we strive for in order to attain future flexibility & maintainability.

In the example above, we can see that an ArrayList<>() yields a List Interface type and a HashMap<>() yields a Map interface type when type inference via the diamond operator is in effect. This is something we expect.

Not the case with “var” which again, is only to be used in a local context. Its scope is limited and thus instead of an interface type, “var”gets you an implementation as the type instead of the interface. As shown above, a new ArrayList<String>() gets you an ArrayList implementation type  and a new HashMap gets you a new HashMap<String,List<Integer>>() implementation type .

At first, this threw me off but in such a local context, your not exposing the implementation outside of this local scope therefore the argument of “Always code to an Interface” fades away. Just be aware of it. If you absolutely need an interface type, then don’t use “var” or use it and then perform a cast … uhhhhh.. ugly .. never mind, don’t get into that mess.

Show me a Really Bad Java var Example!

If used excessively, especially with short non-descriptive identifiers, it can make the code less readable, so use common sense.

What is the returned type from the above method? Sure we can leverage our IDE but it’s not obvious and what if this was a code review? Java “var” can’t hold null but what happens if this method returns null? The method actually returns a Percentage Type which is not obvious when looking at the variable name. I would not want to be the person sucking oxygen on this tank!

Show me a Really Good Java var Example!

I really like using Java “var” while looping through Collections, especially Maps! Let’s take a look at a “before” and “after” code example.

I rather like using Java “var” in this extremely limited scope where its very clear what the type is because who the heck doesn’t know how to loop through a Map! Also, it does cut down on the boiler plate code and make it more readable.

Here is another great use case for Java “var”. Ever work with really really looooong Class names? If you’ve ever worked with Spring then the answer is definitely “yes”!

Believe it or not, that is actually not the longest Class name in Spring .. crazy right?! The example using Java “var” above really makes this more readable, especially when the variable name “screams” what the type is anyways.

Java var Best Practice Advice

If you stick to this best practice advice, you’ll be just fine.

  1. If possible, include some type information with your local identifier name. Identifier name hold more weight now when using var in Java.
  2. Keep the scope of your local “var” variable very short. A few lines at most. No “Where’s Waldo?”  happening. The context has to be clear.
  3. Use it when working with long Class names in order to cut down on repeating the Class name twice. Of course apply Advice Point #1.
  4. Use it when creating objects via static factory methods. The static factory method names usually give away the type information which makes it vry clear if everything is on 1 line.

var support in Java 11 Lambdas

Support for var in Java was included in Java 11 when working with lambdas. This was mainly added for uniformity. The same advice still applies as far as I’m concerned.

Suppose we wanted to use the BiFunction <T, U, R> functional interface to calculate the speed at which you are traveling using formula  speed = distance ÷ time. Here are the options ..

The advantage of using var in lambdas is greatly diminished since we have implicit type inference in the method arguments already. So why use var in lambdas?

If you add an @annotation like @NotNull next to your method parameter, the compiler no longer can resolve the type for you ….  compiler error! To get around this, you must explicitly specify the type.

But, what if your type has a really looooong type name? Ahhh, that’s where you can use Java var in order to have the best of both worlds. It would allow you to eliminate the long Class name and use the @annotation. It’s really an edge case and I don’t find myself really using it in a lambda context. Like I said, it’s mostly there for uniformity.

Summary

Java var is certainly something you can do without. The controversy is rooted in var being misused as well as debating its usefulness when we already have much type inference available.

Var really is no big deal but it can be useful in extreme conditions. Imagine having to work with the longest Class name in the Spring Framework, which is “HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor“. I wish I was joking but I am not! Obviously using Java “var” would avoid you having to include the type on the let hand side … a good thing!

Java “var” is definitely useful when looping over Collections, working with the java.io API and local variable declarations within a try-with-resources.

One last thing!  Java “var” was released in Java 10 and therefore is not backwards compatible. Your “var” code will not be compiled in < 10 JDK versions. Something to be aware of if your still maintaining lots of Java 8 (LTS) projects.

The source code can be found on MVP Java´s GitHub account  here.

If you want to read additional info on Java “var” regarding a style guide then click here.