Locale variable type inference in Java

Java 10, which was released in March 2018, introduced the var keyword. The official name of this new feature is locale variable type inference. So it's about a variable:

String name = "Tonny";

Not any variable, but local variable:

public void aMethod() {
    String name = "Tonny";

Basically, we're saying that it's fun to say name is a String, but the compiler should know the type by itself. Thus, we can replace the type, String in this example, with var:

public void aMethod() {
    var name = "Tonny";

Is Java now JavaScript? Is it now a dynamic language? No, it definetly isn't. It's still staticly defined, but by the compiler.

Improve readability

Should you now change all types of local variables to var? No, please don't.

You should only use var if you think that it will improve the readability of your code. For example, if we have the following code:

URL url = new URL("https://tonnygaric.com");
URLConnection connection = url.openConnection();
BufferedInputStream inputStream = new BufferedInputStream(connection.getInputStream());

We can improve the readability by using var, because the types of the variables are redundant—the names of the variables are self explanatory:

var blogUrl = new URL("https://tonnygaric.com");
var connection = blogUrl.openConnection();
var blogStream = new BufferedInputStream(connection.getInputStream());


By now you know that if you use var, the compiler will define the type of the variable. The compiler will try to be as precise as possible.

We can use jshell to see what types the compiler picks. Note that you must be running JDK 10 or later. We can open jshell with verbose feedback:

jshell -feedback verbose

Or open jshell and set the feedback afterwards on verbose mode:

/set feedback verbose

We can now test what types the compiler would pick, by assigning a value to a variable with the var keyword:

jshell> var i = 1
i == > 1
|  created variable i : int
jshell> var j = 2.0
i ==> 2.0
| created variable j : double

If we use the new collection factory method List.of(), we can see how the compiler can pick the most precise type:

jshell> var list = List.of(1, 2.0d, "three")
list ==> [1, 2.0, three]
|  created variable list : List<Serializable&Comparable<? extends Serializable&Comparable<?>>>

As you can see, a compiler knows how to find more specific and precise types than we -developers- can do.


Assiging null to a variable with keyword var is not allowed:

jshell> var k = null
|  Error:
|  cannot infer type for local variable k
|    (variable initializer is 'null')
|  var k = null;
|  ^-----------^

If you specify more information, for example an explicit cast, it is allowed:

jshell> var k = (Object) null
k ==> null
|  created variable k : Object