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*and not List. If we want it to be ArrayList, we will have to be explicit:

var empList = new ArrayList<Employee>();

Using var with non-denotable types could cause unexpected error.

For example, if we use var with the anonymous class instance:

@Test
public void whenVarInitWithAnonymous_thenGetAnonymousType() {
    var obj = new Object() {};
    assertFalse(obj.getClass().equals(Object.class));
}

Now, if we try to assign another Objectto obj, we would get a compilation error:

obj = new Object(); // error: Object cannot be converted to <anonymous Object>

This is because the inferred type of obj isn’t Object.

5. Conclusion

In this article, we saw the new Java 10 local variable type inference feature with examples.

As usual, code snippets can be found over on GitHub.


» 下一篇: Java 10的性能提升