days
-6
-3
hours
-1
-6
minutes
-2
-8
seconds
0
-7
search
Getting used to type inference

All about var: How Local-Variable Type Inference can clear up Java verbosity

Adrian D. Finlay
var
© Shutterstock / George Dolgikh

One of the most intriguing new features in Java 10 is local-variable type inference. Adrian D. Finlay explores how developers can take advantage of var types to clear up their code from excess Java verbosity.

While Java 10 was not expected to be a major feature release,  it includes a feature that I find invaluable for clearing up Java verbosity: Local-Variable Type Inference!

Now we can have code like this!:

var x = new HashMap<String,Integer>();
//inferred to be HashMap<String,Integer>

Instead of this…

HashMap<String,Integer> x = new HashMap<String,Integer> ();

Experienced readers will quickly see how this will become useful for shortening the syntactic baggage that has been carried along in Java since it’s inception. It doesn’t really serve the language much (in my opinion) to mandate typing the return type on the LHS if we can readily and accurately infer the type from the RHS. It makes for redundant code, which makes for less developer productivity.

I want to thank members of the community, namely: Andriy Drozdyukjeswin, and William Bartlett for voicing their pointed concerns and criticisms of my use of the term “strongly typed”. These criticisms and reviews are part of what makes sure that information is presented as accurately as possible. As a consequence of these conversations, I am now of the opinion that the term “strongly typed” is a very poorly defined defined term, and I will personally avoid using it; This opinion, however, has not been expressed by the aforementioned individuals and is expressly my own.

At the cusp of this issue is that the term “strongly typed” is a colloquially understood term that has no universally accepted meaning. This lends to opinion on meaning, which is inherently messy, and rarely ever appropriate for informative purposes despite it’s frequent use in the developer community and programming related publications and media. As such, this codicil was written to address matters of clarity.

SEE ALSO: 11 experts weigh in: Local-Variable Type Inference is the biggest new feature in Java 10

The trade-off of this is that this (in my opinion) would make Java code less explicitly typed. When considering verbosity, however, it is worth the trade-off, in my opinion.

While this is great for situations where a lot of lasagna code in object instantiation could be avoided, it is perhaps not so good for assigning variables to the result of certain method calls.

Imagine you are working with several methods from various classes (as is the almost ubiquitous case). Is it immediately clear where this call is coming from or what it’s return type is?

public void doGet() { ... }
public void doPost() { ... }
...
var r = doMath(); 
//No clue just by looking at this line alone what type this returns!
//Where did it come from? Not immediately obvious to second hand readers of your code in large projects.

Nope. IDE features, however, help remove a lot of the mystery in quickly figuring out what the returned type will be. Also, how will this mesh with existing Type Inference in Java?

Type Inference with the Diamond Operator

One may think that type inference with the diamond operator cannot be used with local variable type inference but this is not the case. For example:

Map<String,Integer> x = new HashMap <> ();
// Note that we do not need to repeat the paramater arguments
// in the RHS diamond operator as it is induced from the
// RHS return type.
var x = new HashMap<> ();
//Legal!

Personally, I don’t favor this code too much because it is not clear to observers of this code which parameters are instantiated as part of this type. I must admit, however, that this makes for very concise code.

In summa, and in my opinion, var typing can be a good choice in reducing boilerplate when performing object initialization, working with generics, or working with static methods where the enclosing class is explicitly stated (Utilities.doX()).

For other situations, such as assigning a variable to the result of a method call (var x = someMeth()), var typing is not desirable, at least in my opinion.

Java was intent-fully designed to be a statically typed language so that the types of members would be known at compile time. Note that this differs from explicit typing.

While Java has become less explicitly typed, it has still retained the properties about it that make it statically typed and type safe, and it is, again, worth it in my opinion, in the effort to reduce verbosity and improve developer efficiency.

SEE ALSO: Using JDK 10’s local variable type inference with jOOQ

Some Restrictions

1) Use falling outside of these categories

In Java 10, one would only be able to use Local-Variable Type Inference (var) with: 1) local variables with initializers, 2) for-loop indexes, 3) and within the local scope of a conditional loop.
Notice something about this. var can be used with local variable initialization only! Which means you cannot declare a variable as follows:

var x; //No!!! -- Terrible code anyway!

Notice also that this means you cannot use var with Methods, Formals, Fields, or anything else other than the aforementioned. Perhaps Java will add support for var in an upcoming release. Maybe they won’t, time will tell. Either way, they will not be legal Java 10 code.

2) You cannot instantiate multiple variables either

var x=0,y=0; // no! 

3) No Lambdas, Method References, or Array Initializers

4) No null values!

var x = null; //No!
var y = funcReturningNull(); //No! 
// We cannot infer the type.
var x = (Object) null; // This, however, works ;)
//Credit to Olivier Gauthier for this observation.

5) You cannot reassign to a different type

var x=0; //Inferred to be of type 'int'
var x="c"; //No! - incompatible types!

SEE ALSO: How well do you actually understand annotations in Java?

Some other things to know

  • Capture variables used with var are mapped to their supertypes. Any type arguments, if specified are replaced with bounded wildcards.
  • Some Non-Denotable types (like Anonymous Classes) can be inferred by var.

What is var itself?

One might be tempted to believe that var is a keyword. This is in fact, not true. var in Java will a reserved type name. After all, when we type var we are typing it where a type identifier would otherwise be.

The advantage of this is that code that already uses var as the identifier of some member or package won’t be affected because var is not a keyword.

Let’s play with var

Some JShell. Notice that var only works with JDK 10 (of course)!

var

Some compiled examples

var

var

var

For Loop Initializers:

for (var x=0; x<6; x++) { }

SEE ALSO: Java 10: What do Java developers want? Projects Amber and Valhalla! When do they want them? When they’re ready!

Some current error messages of failures with var

var

Remember, it cannot be used with methods or classes!

var v () { return new Object(); } 
//error: 'var' is not allowed here
var class vc { }
//error: 'var' is not allowed here 

Where to learn more about Java 10

Curious about the JDK 10 features? Check them out here.

 

This article was originally published on The Java Report.

Author

Adrian D. Finlay

Adrian D. Finlay is a passionate Software Engineer, blogger, freelancer, tutor & aspiring entrepreneur.

Enthusiastic technology undergraduate seeking work opportunities in Software Development & Engineering. Follow him on Twitter @thewiprogrammer.