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
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);
}The type is still fixed at compile time
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.
Invalid uses of var
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 typeWhen 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
// 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>>();
Situation | Recommendation |
|---|---|
| Good — type is explicit on the right, |
| Fine — everyone knows loop counters are int-like |
| Risky if |
| Avoid — hides a genuinely important type |
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.
varonly works for local variables with an initializer — not fields, parameters, return types, or uninitialized declarations.Use
varwhen the right-hand side already makes the type obvious; avoid it when spelling out the type communicates something useful.