skip to content

Where can you NOT use `var`, and why are those uses disallowed?

level: middleimportance: must knowfreq 65%

answer

  1. Only locals WITH an initializer
  2. No fields, params, return types, catch params
  3. No null, no bare lambda/method ref, no {1,2,3} array form
  4. No multiple declarators (var a=1, b=2)
  5. Allowed in for / enhanced-for / try-with-resources

basics

~20 s

You can only use var for local variables that have a value assigned right away. You cannot use it for class fields, method parameters, method return types, or a local variable declared with no initializer.

solid answer

~50 s

`var` only applies to **local variables with an initializer**, because the compiler needs the right-hand side to infer the type. It is disallowed for: fields/instance variables, method parameters, constructor parameters, method return types, catch-clause parameters, and a bare `var x;` with no initializer. It also cannot infer from `null` alone (no concrete type), from a lambda or method reference that needs a target type (`var f = () -> {}` fails — the compiler has nothing to infer the functional type from), or from an array initializer shorthand (`var a = {1, 2, 3}` fails — that braces form needs a declared array type). You also cannot use `var` for multiple variables in one declaration (`var a = 1, b = 2`). The unifying reason: in every disallowed position the compiler lacks a single, unambiguous initializer expression whose type it can read.

go deeper

for a junior

Knows var needs an initializer and is only for local variables, not fields or parameters.

for a middle

Can list the main disallowed positions (fields, params, return types, no-initializer, null, lambda) and recall it works in for-loops and try-with-resources.

for a senior

Explains the unifying reason (need a single concrete initializer to read) and the poly-expression issue with lambdas/method references and the array-init shorthand.

for a principal

Connects the local-only scoping to API/contract stability and language-design intent; can advise teams on where the restriction prevents fragile signatures.

## The one rule behind every restriction `var` works by **reading the initializer** (the expression after `=`) and copying its type. So `var` is allowed **only** where there is exactly one initializer expression with a clear, concrete type. Every restriction below is just a case where that is missing or ambiguous. ## Where `var` is NOT allowed **1. Fields (instance and static variables).** ```java class C { var x = 1; } // ERROR ``` Fields are part of the class's API and initialization can be split between declaration and constructors; the language deliberately keeps their types explicit. **2. Method/constructor parameters and return types.** ```java void m(var p) {} // ERROR — parameters have no initializer var m() { ... } // ERROR — return type must be explicit ``` A parameter has no initializer at the declaration site; a return type is part of the method signature (the contract), which must be denotable. **3. A local with no initializer.** ```java var x; // ERROR — nothing to infer from x = 5; ``` There is no expression to read the type from. **4. Initializing with `null` alone.** ```java var s = null; // ERROR ``` `null` has no concrete type (it is assignable to any reference type), so there is nothing specific to infer. **5. A lambda or method reference without a target type.** ```java var f = () -> System.out.println("hi"); // ERROR var g = String::length; // ERROR ``` A lambda/method reference is a **poly expression**: it has no type of its own — it takes the type of the *target* (e.g. `Runnable`, `Function`). `var` provides no target, so the compiler cannot decide which functional interface it is. **6. The array-initializer shorthand.** ```java var a = {1, 2, 3}; // ERROR ``` The `{...}` braces form is only legal when an array type is written explicitly. Use `var a = new int[]{1, 2, 3};` instead — now `new int[]{...}` is a self-typed expression. **7. Multiple variables in one declaration.** ```java var a = 1, b = 2; // ERROR ``` Each would need its own inference; the syntax disallows it for clarity. ## What IS allowed (sometimes surprising) - **Local variables in `for` loops**, including enhanced `for`: ```java for (var i = 0; i < 10; i++) { ... } for (var item : list) { ... } ``` - **try-with-resources** variables: `try (var in = new FileInputStream(f)) { ... }`. - **Lambda *parameters*** got `var` in **Java 11** (`(var x, var y) -> x + y`) — but that is a separate feature from inferring the variable itself. ## Why the language designers drew the line here `var` is scoped to **local** variables on purpose. Locals are an implementation detail visible only inside one method, so inferring their type harms nothing externally. Fields, parameters, and return types are **API surface / contracts** — keeping them explicit preserves readable, stable signatures and avoids action-at-a-distance type changes.

  • Can you use `var` for a lambda parameter?
    Yes, since Java 11: `(var x, var y) -> x + y`. But that is inferring the parameter type, not inferring the variable from a lambda — you still cannot write `var f = () -> ...`.
  • Why is `var x = null;` illegal but `String x = null;` fine?
    `null` carries no concrete type, so `var` has nothing to infer. With an explicit type the type comes from the declaration, and `null` is assignable to any reference type.

saying these in an interview costs you the question

  • Saying `var` works for method parameters or return types
  • Believing `var x = null;` compiles
  • Thinking `var f = () -> ...` infers a Runnable/Function
  • Forgetting that a bare `var x;` (no initializer) is illegal
  • Claiming `var` works on fields

context