Member preview

New Java 10 Language Feature: Local-Variable Type Inference (var)!

ATC2016 Innovation Lab

Per the rolling release cycle promise, JDK 10 is schedule to be released on March 20th, 2018.

Not Caught up to Java 9? Learn more below:

While it is not expected to be a major feature release, so far, 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.

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

EDIT (03/21/2018):
I want to thank members of the community, namely: Andriy Drozdyuk, jeswin, 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.

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

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 favour 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.

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. [1]

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!

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.

Grab JDK 10

To get the early the current builds for JDK 10 documentation, visit here:

To install Java 10 on macOS and Windows is pretty straight forward — download the binary, run it, and make sure the environmental variables (PATH) is set. On linux based Operating Systems you will need to download the files to a folder, add the /bin directory to your path(export PATH=$PATH:/… to ./profile on bash, for example) and configure the tools with update-alternatives — install x as well as update-alternatives — config x where x is the tool in question, for example, appletviewer.

When all is done you should get something that looks like this:

$bash on SUSE Linux. I created a folder with some scripts for automating switching between JDKs and openJDKs.

Let’s play with var

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

Some compiled examples.

For Loop Initializers

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

Some Current Error Messages of Failures with 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 targeted new features in JDK 10? Check them out, here.

Want the source? Grab it here.

Java 11 Sneak Peek

See how this feature is upgraded in Java 11!

How do you like var with Java 10?

Looney Tunes Ending [4]

Works Cited

[1] — JEP 286: Local-Variable Type Inference