Java 10: Changing variables as you know them by introducing Local Variable Type Inference

Java 10 is just around the corner with a GA set to March.

One of the biggest news is the Local-Variable Type Inference, which brings improvements to how you're declaring your variables.

Let me explain.

Looking at other languages you often see variable declarations without the type specified. In JavaScript you use the keywords let, const and var, in Scala you use var and val and so on.

Looking at Java you've always had to specify the type when creating a variable — even when the type is obvious from the initialization.

String name = "Luke"  

This can feel a bit verbose, because we know that this is a String since we're assigning "Luke" to the variable straight away.

Introducing the var

This is where Java 10 brings in the game changer — we can now skip specifying the type for local variables and instead simply use the keyword var.

var name = "Luke";  

Cool right?

Now with that said, it's important to realise that even if var is introduced, Java remains a static typed language — meaning that the usage of var only is possible where the type is obvious.

In other words — the type must be possible to infer.

To figure out what that means, let's look at a few do's and dont's.

Only for local variables

First of all, var is only possible for local variables.

Meaning that you can you use it in methods.

void greeting() {  
  var name = "Luke";
  System.out.println("Hello, my name is " + name);
}

//> Hello, my name is Luke

But you can not use it in classes.

class Greeting {

  var name = "Luke";

  void greeting() {
    System.out.println("Hello, my name is " + name);
  }
}

//> error: 'var' is not allowed here

Variables using var must be initialized straight away

When using var you need to make sure to initialize it straight away.

The reason for this is that even if we use var, the compiler needs to determine the type under the hood.

var name = "Luke";  

This means that first declaring a variable, then initializing it at a later stage won't be accepted when using var.

var name;  
name = "Luke";  
//> error: cannot infer type for local variable name

Cannot initialize with lambdas or other poly expressions

This also means that initializing a var variable with a lambda or other poly expressions like method reference will fail, because how would you determine the type?

var nameSupplier = () -> "Luke";  
//> error: cannot infer type for local variable nameSupplier
//  (lambda expression needs an explicit target-type)
var nameFetcher = this::getName;  
//> error: cannot infer type for local variable nameFetcher
//  (method reference needs an explicit target-type)

Cannot use var for method parameters

We also need to keep the classic type declaration for method parameters as well as for constructors.

void greeting(var name) {  
  System.out.println("Hello, my name is " + name);
}

//> error: 'var' is not allowed here

Typical variables to change to var

Now that we got the limitations mapped out, let's look at what you can do.

As long as the target type of the initialized value is clear, we can go ahead and change it to use vars.

var age = 23;

var name = "Luke";

var luke = new Person(age,name);

var names = List.of("Luke", "Eva");

var persons = Map.of("Luke", luke);  

You can reassign vars

You can reassigning a var variable.

var name = "Luke";  
name = "Eva";

System.out.println(name);  
//> "Eva"

One thing to be aware of is that even if you can re-assign a variable like in the example above, you cannot change the type. The type is determined by the first initialization, so an attempt to re-assign to another type would lead to an error.

var name = "Luke";  
name = new Name("Eva");  
//> error: incompatible types: Name cannot be converted to String

Cleaning up loops

Loops are a typical place where you need to declare a local variable.

Let's now clean up a few loops using the var syntax.

var names = List.of("Luke", "Eva");

for (var i = 0; i < names.size(); i++) {  
  System.out.println(names.get(i));
}

//> "Luke"
//  "Eva"
var names = List.of("Luke", "Eva");

for (var name : names) {  
  System.out.println(name);
}

//> "Luke"
//  "Eva"

That's it! Hopefully you now have a clear picture of how you can use the new var declaration type. If you want more information, checkout the proposal JEP-286.