Java 10's var Keyword: Finally, Type Inference
Java 10 is out, and the var keyword is here. Finally, some type inference!
What is var?
The var keyword lets you declare local variables without specifying the type:
// Before
Map<String, List<User>> usersByRole = new HashMap<>();
// After
var usersByRole = new HashMap<String, List<User>>();
The compiler infers the type from the right side.
Where You Can Use It
Only for local variables with initializers:
// Good
var list = new ArrayList<String>();
var name = "John";
var count = 10;
// Bad - no initializer
var x; // Compile error
// Bad - null initializer
var y = null; // Compile error
// Bad - method parameters
public void process(var data) { } // Compile error
// Bad - fields
class MyClass {
var field = "test"; // Compile error
}
When to Use var
1. Long Generic Types
// Before - hard to read
Map<String, List<Map<String, Object>>> config = new HashMap<>();
// After - cleaner
var config = new HashMap<String, List<Map<String, Object>>>();
2. Diamond Operator
// Before
List<String> names = new ArrayList<String>();
// After
var names = new ArrayList<String>();
3. Try-With-Resources
// Before
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
// ...
}
// After
try (var reader = new BufferedReader(new FileReader("file.txt"))) {
// ...
}
When NOT to Use var
1. When Type Isn’t Obvious
// Bad - what type is this?
var result = process();
// Good - explicit
UserResult result = process();
2. Primitive Wrappers
// Bad - Integer, not int
var count = Integer.valueOf(10);
// Good - int
var count = 10;
3. When You Want a Supertype
// Bad - ArrayList, not List
var list = new ArrayList<String>();
// Good - List interface
List<String> list = new ArrayList<>();
Real-World Examples
Streams
// Before
List<String> activeUserNames = users.stream()
.filter(User::isActive)
.map(User::getName)
.collect(Collectors.toList());
// After
var activeUserNames = users.stream()
.filter(User::isActive)
.map(User::getName)
.collect(Collectors.toList());
Loops
// Before
for (Map.Entry<String, List<User>> entry : usersByRole.entrySet()) {
// ...
}
// After
for (var entry : usersByRole.entrySet()) {
// ...
}
Our Team’s Guidelines
We decided on these rules:
- Use var for long generic types
- Don’t use var if type isn’t obvious
- Prefer explicit types for public APIs
- Use var in loops and try-with-resources
The Verdict
var is nice for reducing boilerplate, but don’t overuse it. Readability matters more than brevity.
We’re using it selectively in new code. Not rushing to refactor existing code.
Other Java 10 Features
Application Class-Data Sharing
Faster startup times by sharing class metadata:
java -Xshare:dump
java -Xshare:on -jar myapp.jar
Parallel Full GC for G1
G1 garbage collector now does full GC in parallel. Better performance.
Time-Based Release Versioning
Java now releases every 6 months. Java 10 is the first under this model.
Should You Upgrade?
If you’re on Java 8, wait for Java 11 (LTS release in September 2018).
If you’re on Java 9, upgrade to Java 10. It’s a minor update.
Anyone using var in production? How’s it going?