JavaLocal Variable Type Inference (var)

Local Variable Type Inference (var)

Since Java 10, you can declare a local variable with var instead of spelling out its type, and let the compiler figure the type out from the initializer expression. This is called local variable type inference. It removes repetitive boilerplate on the left-hand side of a declaration without changing anything about how Java’s type system works.

var in action

Java
var name = "Alice";              // inferred as String
var count = 10;                  // inferred as int
var prices = new ArrayList<Double>(); // inferred as ArrayList<Double>
var entry = Map.entry("key", 42);     // inferred as Map.Entry<String, Integer>

for (var i = 0; i < 5; i++) {    // inferred as int
    System.out.println(i);
}
var is not dynamic typing
`var` does **not** turn Java into a dynamically-typed language. The compiler determines the concrete type of the variable at compile time, from the type of the initializer expression, and that type is fixed for the lifetime of the variable — exactly as if you had written it explicitly. `var name = "Alice";` declares a variable of type `String`, full stop; you cannot later assign an `int` to it.

The type is still fixed at compile time

Java
var name = "Alice";
name = 42; // compile-time error: incompatible types: int cannot be converted to String
Where var is and isn't allowed

var only works for local variables that have an initializer — variables declared inside a method, constructor, or initializer block, where the compiler has an expression to infer the type from.

var cannot be used everywhere
`var` is restricted to local variables with an initializer. It cannot be used for: method parameters, method return types, fields (instance or static), or a local variable declared without an initializer (e.g. `var x;` — there is nothing to infer from). It also cannot be initialized to `null` directly, since `null` carries no type information for the compiler to infer.

Invalid uses of var

Java
var x;              // compile error: cannot infer type — no initializer
var y = null;        // compile error: cannot infer type from null
public var greet() { // compile error: var not allowed as a return type
    return "hi";
}
public void log(var msg) { } // compile error: var not allowed as a parameter type
When var helps, and when it hurts

var is most useful when the type is already obvious from the right-hand side, so spelling it out on the left is pure noise — especially with long generic types.

var removing redundant noise

Java
// Before: the type is repeated twice
Map<String, List<Order>> ordersByCustomer = new HashMap<String, List<Order>>();

// After: var removes the redundant right-hand repetition
var ordersByCustomer = new HashMap<String, List<Order>>();
Use var when it aids readability, not just to save keystrokes
Reach for `var` when the initializer already makes the type obvious — `new ArrayList<Order>()`, a constructor call, or a well-named factory method like `Files.newBufferedReader(...)`. Avoid it when the type is genuinely useful information for the reader and isn’t obvious from the right-hand side, such as `var result = process(data);` where `process`’s return type isn’t clear from the call site. In that case, spelling out the real type documents the code for free.

Situation

Recommendation

var list = new ArrayList<Order>();

Good — type is explicit on the right, var avoids repeating it

var i = 0; in a for-loop

Fine — everyone knows loop counters are int-like

var result = calculate();

Risky if calculate()'s return type isn't obvious from its name

var x = getData(); where getData() returns Object

Avoid — hides a genuinely important type

Note
`var` is a **reserved type name**, not a keyword — it only has special meaning as the target of a local variable declaration, so existing code that used `var` as an identifier (a variable, method, or class named `var`) before Java 10 would need to be renamed, but `var` didn’t become a full reserved keyword the way `class` or `if` are.
  • var (Java 10+) infers a local variable's type from its initializer at compile time — it is not dynamic typing.

  • The inferred type is fixed forever; you cannot later assign an incompatible type to that variable.

  • var only works for local variables with an initializer — not fields, parameters, return types, or uninitialized declarations.

  • Use var when the right-hand side already makes the type obvious; avoid it when spelling out the type communicates something useful.