1. The Hook (The "Byte-Sized" Intro)
- In a Nutshell: var (Java 10) = local variable type inference—compiler infers type from initializer. Local variables only (not fields/parameters/return types). Must have initializer (can't be null).
- Benefits: Less verbose (especially generics), readable (focus on name, not type). Not dynamic typing—still strongly typed! Anti-patterns: Obscure types, loss of clarity.
- Best practice: Use when type obvious from right-hand side.
- Works with: Collections, streams, try-with-resources, enhanced for-loop!
Think of restaurant order. Before var = "Give me one medium-sized hot caffeinated beverage of the coffee variety" (verbose!). With var = "Coffee, please" (context makes it obvious). Waiter infers you want coffee. Same clarity, less words!
2. Conceptual Clarity (The "Simple" Tier)
💡 The Analogy
- Explicit type: Spelling out full address ("123 Main Street, Apartment 4B, New York, NY 10001")
- var: Shorthand when context clear ("My place" — listener knows where you live)
3. Technical Mastery (The "Deep Dive")
var Usage Rules
| Can Use | Cannot Use |
|---|---|
| Local variables | Fields |
| Enhanced for-loop | Method parameters |
| Try-with-resources | Method return types |
| Lambda parameters (Java 11) | Without initializer |
4. Interactive & Applied Code
java
import java.util.*;
import java.util.stream.*;
public class VarKeywordDemo {
public static void main(String[] args) {
demonstrateBasicUsage();
demonstrateWithCollections();
demonstrateWithStreams();
demonstrateBestPractices();
demonstrateAntiPatterns();
}
// Basic var usage
static void demonstrateBasicUsage() {
System.out.println("=== BASIC VAR USAGE ===");
// ❌ BEFORE: Verbose explicit types
String message = "Hello";
ArrayList<String> list = new ArrayList<>();
HashMap<String, Integer> map = new HashMap<>();
// ✅ AFTER: Concise with var
var message2 = "Hello"; // Inferred: String
var list2 = new ArrayList<String>(); // Inferred: ArrayList<String>
var map2 = new HashMap<String, Integer>(); // Inferred: HashMap<String, Integer>
System.out.println("message2 type: " + message2.getClass().getSimpleName());
System.out.println("list2 type: " + list2.getClass().getSimpleName());
}
// var with collections
static void demonstrateWithCollections() {
System.out.println("\n=== VAR WITH COLLECTIONS ===");
// Without var (verbose)
List<String> names1 = List.of("Alice", "Bob", "Carol");
Map<String, Integer> ages1 = Map.of("Alice", 30, "Bob", 25);
// With var (concise)
var names2 = List.of("Alice", "Bob", "Carol");
var ages2 = Map.of("Alice", 30, "Bob", 25);
// Enhanced for-loop
for (var name : names2) {
System.out.println("Name: " + name);
}
// Entry iteration
for (var entry : ages2.entrySet()) {
System.out.println(entry.getKey() + " is " + entry.getValue());
}
}
// var with streams
static void demonstrateWithStreams() {
System.out.println("\n=== VAR WITH STREAMS ===");
// Complex generic type — var makes it readable
var numbers = List.of(1, 2, 3, 4, 5);
var evenSquares = numbers.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.collect(Collectors.toList());
System.out.println("Even squares: " + evenSquares);
// Try-with-resources
var path = "data.txt";
try (var reader = new java.io.StringReader("Hello")) {
System.out.println("Reader created");
}
}
// Best practices
static void demonstrateBestPractices() {
System.out.println("\n=== BEST PRACTICES ===");
// ✅ GOOD: Type obvious from RHS
var name = "Alice";
var count = 42;
var list = new ArrayList<String>();
var map = new HashMap<String, Integer>();
// ✅ GOOD: Complex generic types
var result = Map.of(
"users", List.of("Alice", "Bob"),
"admins", List.of("Carol")
);
// ✅ GOOD: Builder patterns
var request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.build();
}
// Anti-patterns to avoid
static void demonstrateAntiPatterns() {
System.out.println("\n=== ANTI-PATTERNS ===");
// ❌ BAD: Type not obvious
var data = getData(); // What type is this?
// ✅ GOOD: Explicit type when unclear
List<String> data2 = getData();
// ❌ BAD: Obscures intent
var x = 10; // Too generic name
// ✅ GOOD: Descriptive name
var maxRetryCount = 10;
// ❌ BAD: Diamond operator makes type unclear
var list = new ArrayList<>(); // ArrayList<Object>? ArrayList<String>?
// ✅ GOOD: Explicit generic type
var list2 = new ArrayList<String>();
}
static List<String> getData() {
return List.of("data");
}
// ❌ CANNOT USE var for:
// var field; // Fields
// void method(var param) {} // Parameters
// var method() { return "x"; } // Return types
// var x; // Without initializer
// var y = null; // null literal
}
// Java 11: var in lambda parameters
class VarInLambdas {
public static void main(String[] args) {
List<String> names = List.of("Alice", "Bob");
// var in lambda (Java 11+)
names.forEach((var name) -> System.out.println(name));
// Useful when you need annotations
names.forEach((@NonNull var name) -> {
System.out.println(name.toUpperCase());
});
}
@interface NonNull {}
}5. The Comparison & Decision Layer
| Scenario | Use var? | Reason |
|---|---|---|
var name = "Alice" | ✅ Yes | Type obvious (String literal) |
var list = new ArrayList<String>() | ✅ Yes | Type explicit on RHS |
var data = getData() | ❌ No | Type unclear |
var x = 10 | ⚠️ Maybe | If name descriptive |
var list = new ArrayList<>() | ❌ No | Generic type unclear |
6. The "Interview Corner" (The Edge)
The "Killer" Interview Question: "Is var dynamic typing like JavaScript?" Answer: NO! var is still strong static typing—just compiler inference!
java
var name = "Alice"; // Inferred: String (not Object!)
// ✅ Strongly typed
System.out.println(name.toUpperCase()); // OK: String method
// ❌ Cannot change type
// name = 42; // COMPILE ERROR: incompatible types
// Compiled code is IDENTICAL to:
String name = "Alice";var = compile-time type inference, NOT runtime dynamic typing!
Pro-Tips:
- When to use var:
java
// ✅ DO: Type obvious
var builder = StringBuilder.new();
var users = List.of("Alice", "Bob");
// ✅ DO: Complex generics
var map = new HashMap<String, List<Integer>>();
// ❌ DON'T: Type unclear
var result = calculate(); // What type?
var x = getValue(); // Unclear!- var doesn't replace good naming:
java
// ❌ BAD: var doesn't fix bad names
var d = getData();
// ✅ GOOD: Descriptive names
var userList = getUserList();