Basics

4. var — Local Variable Type Inference

var lets the compiler infer the type of a local variable from its initializer, reducing boilerplate — but it's not dynamic typing and has strict limits.

Java 10+

Explanation

var (introduced in Java 10 via JEP 286) tells the compiler to infer the static type of a local variable from its initializer. It is purely a compile-time feature — the bytecode is identical to explicitly typed code. Java remains statically typed; var just removes redundant type declarations.

Restrictions: var can only be used for local variables with initializers, for-loop variables, and try-with-resources variables. It cannot be used for fields, method parameters, return types, or lambda parameters (except in Java 11's (var x, var y) -> ... syntax for annotating lambda params).

var hurts readability when the inferred type is not obvious from the right-hand side. var x = process(data); — what is x? Use it when the type is evident (var list = new ArrayList<String>()) and avoid it when it obscures intent.

Example

import java.util.ArrayList;
import java.util.HashMap;

public class VarDemo {
    public static void main(String[] args) {
        // Type is obvious from the right-hand side: good use
        var names = new ArrayList<String>();
        names.add("Alice");
        names.add("Bob");

        // for-loop: common and readable
        for (var name : names) {
            System.out.println(name.toUpperCase()); // compiler knows name is String
        }

        // Also works with primitive inference
        var count = 42;      // inferred as int
        var pi    = 3.14;    // inferred as double

        // Map: still clear because the RHS spells out the type
        var map = new HashMap<String, Integer>();
        map.put("Alice", 1);

        // BAD: type not obvious — avoid var here
        // var result = compute(); // what is result?

        System.out.println("Count: " + count + ", Pi: " + pi);
        System.out.println("Names: " + names);
    }
}

Sources