Learnitweb

Java 10 Local Variable Type Inference

1. Introduction

Before discussing local variable type inference, let us review what is type inference in Java.

Following is the way of declaring a list of String in Java.

List<String> movies = new ArrayList<String>();

// In Java 9, the same piece of code can be written as 
List<String> movies = new ArrayList<>();

The compiler inferences the type of list be looking at the left hand side of the =.

Let us see another example of type inference.

Predicate<Employee> salary = (Employee e) -> e.getSalary() > 1000000

// This line of code can be rewritten using type inference
Predicate<Employee> salary = e -> e.getSalary() > 1000000

Let us now discuss local variable type inference.

Following is a simple way to declaring a variable of type String:

String name = "John";

/* This line of code can be rewritten using local variable type inference:*/

var name = "John";

Here, the type of name is String. The compiler infers the type of name by looking at the right hand side of the ‘=’. Let us see another example.

Employee e = new Employee();

// Above code can be rewritten as 
var e = new Employee();

2. Is Java still Dynamically Typed Language?

After the introduction of the var keyword, Java is still a “statically typed language”. The Dynamically Typed Languages performed type checking at run-time, with var the Java compiler infers the type at compile-time using the type of information provided during variable initialization.

For example, following in not allowed in Java whereas this is allowed in Python which is a dynamically typed language.

var id = 10;
id = "Test";

3. Where can we use var?

3.1 var can be used as local variable with initializer

In the following example, names is a local variable with value initialized as list.

    public static void printNames(){
        var names = List.of("John", "James", "Starc", "Shane");

        for(var name : names){
            System.out.println(name);
        }
    }

3.2 Index in a for loop

In the following example, var is used for each name in the list of Strings names.

    public static void printNames(){
        var names = List.of("John", "James", "Starc", "Shane");

        for(var name : names){
            System.out.println(name);
        }
    }

3.3 try-with-resources

var can be also be used with try-with-resources. In the following example, var can be used for a new resource Scanner.

    public void readFile(){
        try(var scanner = new Scanner(new File("test.txt"))){
            while(scanner.hasNext()){
                System.out.println(scanner.nextLine());
            }
        } catch(FileNotFoundException fileNotFoundException) {
            fileNotFoundException.printStackTrace();
        }
    }

4. Where var can not be used ?

4.1 var can not be used with Class level fields

For example, the following is not possible:

public class Student {
    var firstName;  // not allowed
    var lastname;	// not allowed
}

Let us discuss the reason why var can not be used with class level fields. Suppose you created a class level field with var and initialized with a String. Later if you changed the initialized value to Integer or some other type, this may lead the breaking of code wherever this field of class is used by other objects. Due to this reason var is not allowed with Class level fields.

Instance variables (fields) and class variables (static fields) must have explicit types.

4.2 var can not used as method parameter and return type

var can not be used as method parameter and return type. Following is not allowed:

public class Student {
	public var setName(var name){
	}
}

Let us discuss the reason why var is not allowed as method parameter and return type. Suppose you defined a method with var as method argument and parameter type. Later you changed the return type or method parameter. This may lead to errors wherever this method is used in other objects. Due to this reason var is not allowed as method parameter and return type.

4.3 Array initializer expressions

When initializing an array using an array initializer expression, you cannot use var.

var array = {1, 2, 3}; // This is not allowed

4.4 Constructor parameters

Similar to method parameters, constructor parameters also require explicit types.

ClassName(var param) { // This is not allowed
    // constructor body
}

4.5 var is not allowed as catch formal

Following is not allowed:

    public void test() {
        try{
            // try body
        } catch(var e){ // not allowed
            // catch body
        }
    }

5. Few important points to note

  • var is a reserved type name, not a keyword, which means that existing code that uses var as a variable, method, or package name is not affected. However, code that uses var as a class or interface name is affected and the class or interface needs to be renamed.
    var var = 10; // Allowed but should be avoided
  • local variable declared using var are not final. You can use final with var. For example,
    final var = 10;
  • Local variable with var always need an initializer. For example, following is not allowed:
    var x;
    Let us discuss why local variable with initializer is not allowed. Suppose, if you write the code something like the following:
    var x;
    var x;
    ............
    ............
    x = 10;
    Here, x is initialized to a string value and later with an integer value. The type of code is changed later from String to int. This may lead to confusion regarding the type of variable and errors. That is why some value is provided when variable is declared which specifies the type of variable.
  • You should be specify the type where the requirement is very specific. For example:
    byte x = 10; // this is byte
    var y = 10; // this is int

6. Conclusion

Java 10 introduced local variable type inference with the var keyword, offering developers a means to write more concise and readable code. By allowing the type of local variables to be inferred from their initialization expressions, Java code becomes less verbose without sacrificing type safety. This feature enhances developer productivity by reducing boilerplate code, especially in scenarios where variable types are evident from the context. While var facilitates cleaner code, it’s essential for developers to use it judiciously, ensuring that their code remains understandable and maintainable. Overall, Java 10’s local variable type inference with var represents a significant step forward in modernizing the Java language, making it more expressive and developer-friendly.