Local-Variable Type Inference with 'var'

Declaring local variables is much simpler with the Java 10 reserved word 'var'.

Tutorial | Jan 25, 2020 | mbrown 

Overview

Manifest typing or explicit type identification of variables is an inherent characteristic of statically-typed languages, such as Java, C++, and C#. These are some examples of explicit type declarations of local variables in Java:

//'i' explicitly declared as 'int' 
int i = 10; 

//'ai' explicitly declared ArrayList<Integer>
ArrayList<Integer> ai = new ArrayList<Integer>(); 

However, over the past few years, a consensus has been developing that programmers should be allowed to omit the explicit type of the variables wherever compilers can infer it. The Local-Variable Type Interference (LVTI), introduced in Java 10, is part of that emerging trend. The LVTI permits developers to drop ceremonious manifest type of local variables without compromising the static type safety of the language, as shown below:

//'i' is inferred int implicitly
var i = 10; 

//'ai' is inferred ArrayList<Integer>
var ai = new ArrayList<Integer>();    

In the above examples of LVTI, we declare the local variables using the reserved word var instead of an explicit type and leave it to the compiler to infer the actual type of the variables from the RHS initializers.

Description

The LVTI reduces the monotony associated with writing the Java code by eliminating the unnecessary boilerplate type declarations of local variables. As its name suggests, the LVTI is limited to only local variables where the type of a variable can be inferred from an initializer in RHS. The LVTI does not work for method parameters, catch parameters, fields, or method return types. These are some more compelling examples of LVTI:

// A complex HashMap
var hmap = new HashMap<Integer, ArrayList<String>>();

//Array of strings
var arr  = new String[] { "Hello", "World" };

//A for-loop variable
for (var s : arr) {
    System.out.println(s);
}

These are some examples of local variable declarations where LVTI does not work because the compiler cannot infer the type of the variables:

//Missing initializer on RHS
var x; //ERROR

//null initializer 
var n = null; //ERROR

//Lambda requires an explicit type
var l = () -> { }; //ERROR

//Array initializer requires explicit type
var arrint = { 10, 78, 90 }; //ERROR

It is also worth mentioning here that for the backward compatibility reasons the var is not a keyword, it is a reserved word. That means it is perfectly fine if your existing codebase has variables, methods, or a package named var. However, a user-defined type - a class or an interface - cannot be named var since Java 10. These are some examples:

//'var' is variable inferred as 'int'
var var = 10;  

class X {
 //....
 //method var returns int
 int var() { return 10; } 
}

//class cannot be named 'var'
class var { ... } // ERROR

Note that for the sake of readability the new codebases should avoid naming the variables or methods as var.

Further Reading

JEP 286: Local-Variable Type Inference

Manifest Typing - Wikipedia

2015 nextptr