Local Variable Type Inference (var)
var lets you declare a local variable without writing its type — the compiler infers one fixed static type from the value on the right, keeping your code concise while staying fully type-safe.
Learn Local Variable Type Inference (var) in our free Java course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a…
Part of the free Java course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
Before You Start
You should be comfortable with data types and variables and have seen generic collections like List<String> . var needs Java 10 or newer (Java 11+ for lambda parameters).
What You'll Learn
The Big Idea — A Label You Don't Have to Write
💡 Analogy: Imagine moving house. When a box is clearly a kettle , scrawling "KETTLE" on the side is just noise — anyone can see what it holds. var is letting the box speak for itself: var kettle = new Kettle(); still is a kettle box (the type is fixed), you just didn't bother writing the label twice. But for a plain cardboard box of mystery cables, you do want a label — that's when you keep the explicit type.
The key point: the type still exists and is permanent. var never makes a variable "any type". It simply spares you from repeating a type the compiler can already see.
1️⃣ How var Infers a Type
When you write var x = expression; , the compiler looks at the type of expression and gives x exactly that type — permanently. var name = "Ada"; is compiled identically to String name = "Ada"; . There is no runtime difference at all.
2️⃣ var in for Loops
Loops are where var earns its keep. In a classic loop, for (var i = 0; ...) infers int . In an enhanced loop, for (var item : list) infers the collection's element type. Iterating a map's entrySet() normally means typing Map.Entry<String, Integer> — with var it collapses to three letters.
3️⃣ Readability & the Diamond Trap
Use var when the right-hand side already states the type — var list = new ArrayList<String>(); is clean. Avoid it when the type is hidden behind a method call — var x = service.process(); forces the reader to go hunting. A good explicit type is documentation; don't throw it away.
There is also a subtle trap with the diamond operator <> . Because var infers from the right-hand side, var list = new ArrayList<>(); infers ArrayList<Object> — almost never what you want. Put the type argument on the right.
4️⃣ Where var Is NOT Allowed
var is strictly a local variable feature. Each line below is a compile error:
🧠 Quick Recall
Predict the result before opening each answer.
Answer: double . Mixing an int with a double promotes the result to double , so x is 7.0 , a double .
Answer: No. msg was inferred as String and that's permanent, so assigning the int 42 is error: incompatible types .
Answer: It compiles, but items is ArrayList<Object> because the bare diamond infers Object . You lose type safety on the elements. Fix it: new ArrayList<String>() .
🎯 Your Turn — Sum word lengths with var
Use var for both the accumulator and the loop variable to total every word's length.
🧩 Mini-Challenge — Find the hottest reading
Track a running maximum across a list of temperatures using var throughout.
Common Errors
- ❌ Using var on a field or parameter. error: 'var' is not allowed here . Fix: spell out the type — var is locals only.
- ❌ var x; with no initializer. error: cannot infer type for local variable x . Fix: give it a value to infer from.
- ❌ var y = null; null has no concrete type. Fix: use an explicit type, e.g. String y = null; .
- ❌ var list = new ArrayList<>(); infers ArrayList<Object> . Fix: put the type on the right: new ArrayList<String>() .
- ❌ Expecting var to be dynamic. It is not — the type is fixed at compile time. Fix: treat it exactly like the explicit type it stands for.
- ❌ Hiding an opaque method's type behind var . Hurts readers. Fix: write the explicit type when the right-hand side doesn't reveal it.
Pro Tips
- 💡 Let the right-hand side carry the type. The best var lines are constructor calls and factory methods where the type is right there.
- 💡 Name variables well. With the type gone, a clear name like customerCount does more of the documenting.
- 💡 var works with lambda parameters since Java 11 — useful only when you need an annotation on the parameter: (@NonNull var x) -> ... .
- 💡 Hover in your IDE to see the inferred type instantly — a quick way to confirm var guessed what you expected.
📋 Quick Reference
Concept
Syntax
Note
String local
var s = "hi";
Inferred String
int local
var n = 42;
Inferred int, fixed
double local
var d = 1.5;
Decimal literal = double
Generic list
var l = new ArrayList<String>();
Type on the RIGHT
Classic loop
for (var i = 0; ...)
i is int
Enhanced loop
for (var x : list)
x = element type
Map entry loop
for (var e : map.entrySet())
Avoids long Entry type
Field
var f = 1; // in class body
❌ Not allowed
Parameter / return
void m(var p)
No initializer
var x;
❌ Compile error
null initializer
var x = null;
❌ No type to infer
Bare diamond
var l = new ArrayList<>();
⚠️ Infers Object
📚 Resources / Keep Learning
- 📘 Oracle: Local Variable Type Inference — the official language guide.
- 📗 dev.java: Using the var Keyword — a guided tutorial with style guidance.
- 📙 JEP 286: Local-Variable Type Inference — the original proposal and rationale.
❓ Frequently Asked Questions
🎉 Lesson Complete!
You can now use var to drop redundant local-variable types, you know it stays statically typed, and you know exactly where it's forbidden (fields, parameters, returns, and uninitialized or null declarations). You also know to keep the type argument on the right of a generic.
Next up: Text Blocks — multi-line string literals that make JSON, SQL, and HTML readable.
Practice quiz
What does var do in Java?
- Declares a dynamically typed variable
- Creates a global variable
- Infers the variable's static type from its initializer
- Makes a variable mutable
Answer: Infers the variable's static type from its initializer. var keeps Java statically typed — the compiler infers a single fixed type from the right-hand side.
In which Java version was local-variable type inference (var) introduced?
- Java 10
- Java 8
- Java 11
- Java 17
Answer: Java 10. var arrived in Java 10 (JEP 286). Java 11 later allowed it in lambda parameters.
Where is var NOT allowed?
- A local variable inside a method
- A for-loop index
- An enhanced for loop
- A class field (instance variable)
Answer: A class field (instance variable). var works only for local variables, indexes, and loop variables — never for fields, method parameters, or return types.
What happens with: var x;
- x is null
- It fails to compile
- It infers Object
- x is 0
Answer: It fails to compile. var needs an initializer to infer from. var x; has nothing to infer, so it is a compile error.
After var n = 42; can you later write n = "hi";?
- No, n is fixed as int
- Yes, var is dynamic
- Only with a cast
- Only inside a loop
Answer: No, n is fixed as int. var infers int once; the type is permanent, so assigning a String is a compile error.
What type is inferred by var price = 19.99;?
- float
- BigDecimal
- double
- String
Answer: double. A floating-point literal like 19.99 is a double, so price is inferred as double.
Is var a reserved keyword in Java?
- Yes, you can never use it as an identifier
- No, it is a reserved type name — you can still name a method var
- It is deprecated
- Only in modules
Answer: No, it is a reserved type name — you can still name a method var. var is a 'reserved type name', not a full keyword, so older code that used var as a variable or method name still compiles.
Why prefer the explicit type argument with var, e.g. var list = new ArrayList<String>();?
- var requires it for performance
- ArrayList cannot use var
- It is required syntax
- The diamond <> would make the element type Object
Answer: The diamond <> would make the element type Object. var takes its type from the right-hand side, so a bare diamond new ArrayList<>() would infer ArrayList<Object>. Put the type argument on the right.
Which is the BEST use of var for readability?
- var x = compute();
- var map = new HashMap<String, List<Order>>();
- var y = 1;
- var z = service.fetch();
Answer: var map = new HashMap<String, List<Order>>();. var removes the most noise when the right-hand side already states a long, obvious type like HashMap<String, List<Order>>.
Can var be used in an enhanced for loop, like for (var item : items)?
- No
- Only for arrays
- Yes, item is inferred from the collection's element type
- Only for List
Answer: Yes, item is inferred from the collection's element type. var works in both classic and enhanced for loops; the loop variable's type is inferred from the iterable.
Continue this course
- Previous: Data Types
- Next: Text Blocks