May 10, 2022

Java var Type (Local Variable Type Inference)

In this post we’ll discuss a feature called local variable type inference which is included in Java 10. A new reserved type name "var" is added in Java to define and initialize local variables. Note that var is not a keyword, it’s a reserved type name. So your existing variable named var still works and you can still create any field, method, package named var.

Type inference in Java

First let’s try to understand what exactly is this type inference.

String str = "test";

List<String> cityList = List.of("New Delhi", "Chicago", "London");

In the above two statements types on the left hand-side may feel redundant and obvious. Java being a static type language requires that type of each variable has to be declared explicitly, even if type is obvious you have to declare it.

var type introduced in Java 10 helps in reducing that verbosity in the code by inferring the type of the local variable using the expression on the right side. You no longer need to declare the type of the variable, it will be inferred by the compiler from the variable initializer. So, the above two statements can now (Java 10 onward) be written as.

var str = "test";
var cityList = List.of("New Delhi", "Chicago", "London");

Let’s see if the type is inferred or not-

System.out.println("Type of str- " + str.getClass().getName());
System.out.println("Type of cityList- " + cityList.getClass().getName());

gives output as-

Type of str- java.lang.String
Type of cityList- java.util.ImmutableCollections$ListN

So you can see how using var, type of the local variable is inferred by the compiler itself rather than you explicitly declaring the type of each variable.

The main advantage of local variable type inference feature is to reduce boilerplate variable type definitions and to increase code readability.

Since most of the libraries in Java are made up of generic classes and methods that means you will have more and more generics parameterized by further generic types. Here is an example showing such a scenario where you need to iterate a HashMap of ArrayLists of String.

Map<String, List<String>> citiesCountryWise = new HashMap<String, List<String>>();
// getData() method provides the data
citiesCountryWise = getData();

// iterating over a map
for(Map.Entry<String, List<String>> entry : citiesCountryWise.entrySet()){
    // iterating over a list
    for(String cityName : entry.getValue()){
        System.out.println("City - " + cityName);
    }
}

Using local variable type inference the same code can be shorten to aid readability.

var citiesCountryWise = new HashMap<String, List<String>>();
citiesCountryWise = getMap();

// iterating over a map
for(var entry : citiesCountryWise.entrySet()){
    // iterating over a list
    for(String cityName : entry.getValue()){
        System.out.println("City - " + cityName);
    }
}

Points about local variable type inference

1. Each of the expressions using var still has a static type i.e. the declared type of a value. This means that assigning a different value will fail.

For example in the following statement type of i is inferred as int by compiler

var i = 10;

Now this type can't be changed, any such attempt results in compile time error.

i = "test"; // Type mismatch: cannot convert from String to int

2. var doesn’t work well with polymorphic code. For example let’s take a simple class hierarchy of Animal as a super class and two child classes Cat and Dog.

In that case if the Object of class Cat is created as given below

var c = new Cat();

Then what would be the type of c? Animal or Cat? As already stated type of the local variable is the type of the initializer so c is of type Cat here.

Trying to make following assignment results in error.

c = new Dog(); // Type mismatch: cannot convert from Dog to Cat

So the polymorphic code that we can usually write as follows is not possible with var.

Animal a = new Cat();
a = new Dog();

3. var is used for local type inference so it can’t be used with fields and in method signatures. Following is not possible.

public void display(var str) { 
  ....
  ....
}

4. You cannot use local variable declarations without an explicit initialization. Since type is inferred from the expression on the right side so having that is mandatory.

var a; // Cannot use 'var' on variable without initializer

5. var variable cannot be initialized to null. With null, type is not clear so any such assignment results in compile time error.

var a = null; //Cannot infer type for local variable initialized to 'null'

6. You cannot use var with lambda expressions because they require an explicit target-type.

var x = (a, b) -> a+b;

This lambda expression will fail with the compilation error "Lambda expression needs an explicit target-type"

That's all for the topic Java var Type (Local Variable Type Inference). If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment