Thursday, June 11, 2020

Var type in Java - Local Variable Type Inference

Java 10 introduced a new feature called local variable type inference where the type of the variable is inferred from the variable initializer. For this a new reserved type name “var” is added in Java to define and initialize local variables. Note that “var” is not a reserved keyword Java 10 onward it is a reserved type name so no worries if you already have an existing variable named var.


Type inference in Java- How it helps

Java is a static typed language that means any variable that is used must be defined with appropriate type. Consider the following statements-

int i = 10;
String s = “Hello”;
List<String> names = new ArrayList<String>();
Person p = new Person();

You have to declare the variable with its type before initializing it that seems simple but at the same time it can be argued that in these statements type of the variable can easily be inferred from the context.

s has to be of type String and names hold an ArrayList reference. That’s what local variable type inference does using the “var” type.

Java 10 onward, these statements can be written as follows using the var type.

var s = "test";
var names = new ArrayList<String>();

You can check whether the correct type in inferred by the compiler or not.

System.out.println("Type of s- " + s.getClass().getName());
System.out.println("Type of ArrayList- " + names.getClass().getName());

Output

Type of s- java.lang.String
Type of ArrayList- java.util.ArrayList

As you can see type is correctly inferred.

The main benefit of using var type is the increased readability. From the above two statements that point may not be that clear but consider the scenario where you have generics parameterized by further generic types. For example you have a HashMap that stores ArrayLists.

Map<String, List<String>> mapValues = new HashMap<String, List<String>>();

And then you have to iterate this HashMap of ArrayList using the entry set.

for(Map.Entry<String, List<String>> entry : mapValues.entrySet()){
    for(String s : entry.getValue()){
              System.out.println("Value - " + s);
    }
}

That’s a lot of angular brackets! Same thing can be written in a simpler form using local variable type inference.

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

While iterating-

for(var entry : mapValues.entrySet()){
    for(String s : entry.getValue()){
        System.out.println("Value - " + s);
    }
}

Does var make Java dynamically typed

Though var type brings the convenience of not forced to give the exact type of the variable but it doesn’t make it dynamic by any means. Once a variable is declared using var type, variable is bound to the inferred type never to be changed again.

For example consider the following statement-

var s = "Hello";

Type of s is inferred as String by the compiler and this type can't be changed. If you try to assign an int value to variable s-

s = 7; 

you will get a compile time error "Type mismatch: cannot convert from int to String".

Restrictions with local variable type inference

1. You cannot use local variable type inference with fields and in method signatures. It’s only for local variables.

public void doCalculation(var i) {
  ..
  ..
}

Such method signature will give you compile time error “'var' is not allowed here”.

2. A var variable cannot be initialized to null.

var s = null; 

The above statement will result in a compile time error “Cannot infer type for local variable initialized to 'null'”.

3. You cannot use local variable declarations without an explicit initialization. Since the type of the variable is inferred from the value assigned to it so initialization is necessary, you cannot just use the var syntax to declare a variable without a value.

var s;

The above statement will result in a compile time error “Cannot use 'var' on variable without initializer”.

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

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

Above lambda expression results in compile time error “Lambda expression needs an explicit target-type”.

5. var doesn’t work well with polymorphic code. Consider the scenario where you have a Parent class named Parent and two child classes Child1 and Child2 then, because of run-time polymorphism the following statements are perfectly fine-

Parent p = new Child1();
p = new Child2();

Parent class can store reference of both Child1 and Child2. But with var if you have a statement as following-

var p = new Child1(); 

Compiler has no way of knowing whether you intended p to be of type Parent or Child1. Since type of var is inferred to be the type of the initializer so here p will be considered to be of type Child1. That means following assignment results in error.

p = new Child2(); // Type mismatch: cannot convert from Child1 to Child2

That's all for this topic Var type in Java - Local Variable Type Inference. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. JShell in Java With Examples
  2. Private Methods in Java Interface
  3. String join() Method And StringJoiner Class in Java
  4. New Date And Time API in Java 8
  5. Java Stream API Tutorial

You may also like-

  1. Method Reference in Java
  2. String Pool in Java
  3. Switch Expressions in Java 12
  4. Connection Pooling Using Apache DBCP in Java
  5. Named Tuple in Python
  6. Angular - Call One Service From Another
  7. Spring Boot Hello World Web Application Example
  8. Using Avro File With Hadoop MapReduce