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:

  1. Use var for long generic types
  2. Don’t use var if type isn’t obvious
  3. Prefer explicit types for public APIs
  4. 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?