Java 10: Local Variable Type Inference

Java 10: Local Variable Type Inference
Java 10 (March 2018) introduced the var keyword for local variable type inference, reducing boilerplate code while maintaining type safety. This was a short-term support release, but introduced a significant feature.
1. Local Variable Type Inference with var
The var keyword allows the compiler to infer the type of local variables.
Before Java 10:
// Verbose type declarations
ArrayList<String> names = new ArrayList<>();
String message = "Hello, World!";
Map<String, Integer> scoreMap = new HashMap<>();
List<? extends Number> numbers = Arrays.asList(1, 2, 3);
Iterator<String> iterator = names.iterator();After Java 10:
// Type inference with var
var names = new ArrayList<String>();
var message = "Hello, World!";
var scoreMap = new HashMap<String, Integer>();
var numbers = Arrays.asList(1, 2, 3);
var iterator = names.iterator();2. When to Use var
Using var effectively requires understanding when it improves readability.
// ✓ Good: Type is obvious from right side
var users = getUserList(); // Good - clear what getUserList returns
var connection = createConnection(); // Good - clear intent
var count = 42; // Good - obvious it's an int
// ❌ Not recommended: Type not obvious
var x = getComplexObject(); // Unclear what type x is
var result = performCalculation(); // Vague what result contains
// ✓ Good: Works well with enhanced for-loops
Map<String, List<Integer>> data = new HashMap<>();
for (var entry : data.entrySet()) {
var key = entry.getKey();
var values = entry.getValue();
}
// ✓ Good: Simplifies generic code
for (var user : getUserList()) {
System.out.println(user.getName());
}3. var with Lambda Expressions
Lambda parameters can now use var for better readability.
// Before Java 10 (Lambda parameters couldn't use var)
(String name, int age) -> System.out.println(name + ": " + age);
// After Java 11 (var in lambdas)
(var name, var age) -> System.out.println(name + ": " + age);
// With annotations
stream.forEach((var user) -> processUser(user));4. Constraints on var
Variables declared with var must be initialized immediately.
// ✓ Valid: Must initialize
var list = new ArrayList<String>();
// ❌ Invalid: Cannot omit initializer
var list2; // Compilation error
// ❌ Invalid: Cannot use null without explicit type
var value = null; // Compilation error
// ✓ Valid: Explicit cast when needed
var value2 = (String) null;
// ❌ Invalid: Cannot use var in multiple declaration
var x = 1, y = 2; // Compilation error
// ✓ Valid: Use separate declarations
var x = 1;
var y = 2;5. Parallel Garbage Collection
G1GC became the default garbage collector, improving pause times for large heaps.
// Before Java 10: Serial GC for small heaps
// java -XX:+UseSerialGC MyApp
// After Java 10: G1GC is default
// Automatic optimization for heap-sized applications6. Unmodifiable Collections
New methods for creating unmodifiable collection copies.
List<String> original = new ArrayList<>(Arrays.asList("a", "b", "c"));
// Before Java 10
List<String> copy = Collections.unmodifiableList(
new ArrayList<>(original)
);
// After Java 10: Shorter syntax
List<String> copy = List.copyOf(original);
Set<String> setCopy = Set.copyOf(original);
Map<String, Integer> mapCopy = Map.copyOf(original);Developer Impact
Positive:
- Reduced Verbosity: Less typing, more focus on logic
- Improved Readability: Cleaner code in many cases
- Type Safety: Compiler still enforces types
- Faster Development: Less mental overhead on declarations
Challenges:
- Less Explicit: Some developers prefer explicit types
- Readability Trade-off: Can reduce clarity if misused
- IDE Dependency: Benefits from good IDE support for type hints
Pros and Cons
Pros ✅
- Concise Code: Reduces repetitive type declarations
- Type Safe: Full compile-time type checking maintained
- Better Readability: Especially with complex generics
- Reduced Errors: Less chance of type mismatch typos
- Modern Language Feel: Makes Java feel more concise
- Copyable Collections: Safer defensive copying
Cons ❌
- Reduced Explicit Types: Harder to understand code without IDE hover
- Learning Curve: Developers must know when to use var
- Not Everywhere: Cannot use var for fields, method parameters (in Java 10), return types
- Debugging: Stack traces less informative
- Code Review: Harder to spot intent in pull requests
Usage Guidelines
// ✓ USE VAR when:
// 1. Type is obvious from right-hand side
var user = new User("John", 30);
var users = userRepository.findAll();
// 2. Working with generics
var cache = new HashMap<String, CachedValue>();
var entries = cache.entrySet();
// 3. Loop variables
for (var user : users) { }
// ✗ AVOID VAR when:
// 1. Type is not immediately obvious
var data = complex.calc.compute(); // What type?
// 2. Returning from library methods with unclear names
var result = externalLibrary.doSomething();
// 3. Numeric literals that could be confusing
var count = 1000000; // Is this int or long?Conclusion
Java 10's var keyword is a quality-of-life improvement that reduces boilerplate code. While it doesn't add powerful new features, it makes code more concise and the language more enjoyable to use. The key is using it judiciously to improve readability, not obscure intent.
Best Practice:
- Use
varwhen the type is obvious from context - Prefer explicit types for public APIs
- Let your IDE help show inferred types