Chapter 7. Local-Variable Type Inference

7.1.  Use local-variable type inference

[Note]
  • [LVTI_STYLE] Style Guidelines for Local Variable Type Inference in Java

Type inference refers to the automatic detection of the datatype of a variable, done at compile time.

Local variable type inference is a feature in Java 10.0 that allows the developer to skip the type declaration associated with local variables (those defined inside method definitions, initialization blocks, for-loops, and other blocks like if-else), and the type is inferred by the JDK. It will, then, be the job of the compiler to figure out the datatype of the variable.

In Java 11.0 the local variable type inferrence was extended for lambda parameters (see details in the next section).

[Important]

Despite the introduction of var, Java is still a statically typed language, and there should be enough information to infer the type of local variable. If not, the compiler will throw an error.

The var IS NOT a keyword. Instead, it is a reserved type name. This means that existing code that uses var as a variable, method, or package name WILL NOT be affected.

Existing code that uses var as a class or interface name WILL be affected.

Legal type inferrence usage

  • In a static/instance initialization block:

    class A { 
        static  { 
            var s = "Hello, Java!";         
        }
        
        {
            var s = "Hello, World!";
        }
    }
    								

  • As a local variable in a method:

    public static void main(String[] args) {
        var s = "Hello, Java!";
    }
    								

  • As iteration variable in enhanced for-loop:

    
    List<String> l = List.of("Hello", ", ", "Java!");
    for (var s : l) {
        System.out.print(s);
    }    
    
    								

  • As looping index in for-loop:

    for (var i = 0; i < 10; i++) {
        System.out.print(i);
    }    
    								

  • As a value from another method:

    public static void main(String[] args) {
        var x = getId();
    }
    static int getId() {
      return 1;
    }
    								

  • As a return value in a method:

    public static void main(String[] args) {
        int x = getId();
    }
    static int getId() {
        var id = 1;
        return id;
    }
    								

  • As resource variable in the try-with-resource block:

    public void printFile() throws IOException {
        try (var input = new FileInputStream("file.txt")) {
            ...
        }
    }
    								

Illegal type inferrence usage

  • Not permitted as class field:

    public class A {
        static var i = 0;
    }
    								

  • Not permitted as instance variable:

    public class A {
        var i = 0;
    }
    								

  • Not allowed as local variable without initialization:

    public static void main(String[] args) {
        var x;
    }
    								

  • Not allowed as parameter for a method:

    public static void main(var[] args) {
        ...
    }
    
    public void println(var x) {
        System.out.print(x)
    }
    								

  • Not allowed as method return type in method signature:

    public var getId() {
        return 1;
    }								

  • Not allowed with explicit initialization to null:

    public static void main(String[] args) {
        var x = null;
    }								

    [Warning]

    Can be initialized to null with explicit cast:

    public static void main(String[] args) {
        var x = (Integer) null;  // compiles OK
    }
    									

  • Not allowed to reassign to a different [incompatible] type:

    public static void main(String[] args) {
        var x = 0;  // inferred to be of type int
        x = "Java"; // ERROR - String cannot be converted/assigned to int
    }
    								

  • Not allowed in compound declaration, i.e. when we declare multiple local variables, even with initialization:

    public static void main(String[] args) {
        var x, y = 0;
    }
    								

  • Not allowed as lambda expression type (still needs an explicit target type):

    public static void main(String[] args) {
        var p = (String[] s) -> s.length > 0;
    }
    								

  • Not allowed with array initializer (an array initializer still needs an explicit target type):

    public static void main(String[] args) {
        var arr = {1, 2, 3};
    }
    								

  • Not allowed with method reference (still needs an explicit target type):

    public static void main(String[] args) {
        var unaryOp = String::toLowerCase;
    }
    								

Professional hosting         Exam 1Z0-817: Upgrade OCP Java 6, 7 & 8 to Java SE 11 Developer Quiz     Exam 1Z0-810: Upgrade to Java SE 8 Programmer Quiz