1. Overview
One of the most visible enhancements in JDK 10 is type inference of local variables with initializers.
This tutorial provides the details of this feature with examples.
2. Introduction
Until Java 9, we had to mention the type of the local variable explicitly and ensure it was compatible with the initializer used to initialize it:
String message = "Good bye, Java 9";
In Java 10, this is how we could declare a local variable:
@Test
public void whenVarInitWithString_thenGetStringTypeVar() {
var message = "Hello, Java 10";
assertTrue(message instanceof String);
}
We don’t provide the data type of message. Instead, we mark the message as a var, and the compiler infers the type of message from the type of the initializer present on the right-hand side.
In above example, the type of message would be String.
Note that this feature is available only for local variables with the initializer. It cannot be used for member variables, method parameters, return types, etc – the initializer is required as without which compiler won’t be able to infer the type.
This enhancement helps in reducing the boilerplate code; for example:
Map<Integer, String> map = new HashMap<>();
This can now be rewritten as:
var idToNameMap = new HashMap<Integer, String>();
This also helps to focus on the variable name rather than on the variable type.
Another thing to note is that var is not a keyword – this ensures backward compatibility for programs using var say, as a function or variable name. var is a reserved type name, just like int.
Finally, note that there is no runtime overhead in using var nor does it make Java a dynamically typed language. The type of the variable is still inferred at compile time and cannot be changed later.
3. Illegal Use of var
As mentioned earlier, var won’t work without the initializer:
var n; // error: cannot use 'var' on variable without initializer
Nor would it work if initialized with null:
var emptyList = null; // error: variable initializer is 'null'
It won’t work for non-local variables:
public var = "hello"; // error: 'var' is not allowed here
Lambda expression needs explicit target type, and hence var cannot be used:
var p = (String s) -> s.length() > 10; // error: lambda expression needs an explicit target-type
Same is the case with the array initializer:
var arr = { 1, 2, 3 }; // error: array initializer needs an explicit target-type
4. Guidelines for Using var
There are situations where var can be used legally, but may not be a good idea to do so.
For example, in situations where the code could become less readable:
var result = obj.prcoess();
Here, although a legal use of var, it becomes difficult to understand the type returned by the *process()*making the code less readable.
java.nethas a dedicated article on Style Guidelines for Local Variable Type Inference in Java which talks about how we should use judgment while using this feature.
Another situation where it’s best to avoid var is in streams with long pipeline:
var x = emp.getProjects.stream()
.findFirst()
.map(String::length)
.orElse(0);
Usage of var may also give unexpected result.
For example, if we use it with the diamond operator introduced in Java 7:
var empList = new ArrayList<>();
The type of empListwill be *ArrayList