Where can you NOT use `var`, and why are those uses disallowed?
answer
- Only locals WITH an initializer
- No fields, params, return types, catch params
- No null, no bare lambda/method ref, no {1,2,3} array form
- No multiple declarators (var a=1, b=2)
- Allowed in for / enhanced-for / try-with-resources
basics
~20 sYou 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
Knows var needs an initializer and is only for local variables, not fields or parameters.
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.
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.
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