Skip to Content
Course content

22: The var Keyword for Local Type Inference

Click on the "Edit" button in the top corner of the screen to edit your slide content.

For years, Java had a reputation for being "verbose." If you've been following along with the course, you've probably felt this. We've spent a lot of time writing things like List<UserAccount> users = new ArrayList<>();. It's clear, sure, but it's repetitive. You're essentially saying "this is a list of users" twice in one line.

That's why Java introduced the var keyword. It allows for local variable type inference. Basically, you're telling the compiler, "You're smart enough to look at the right side of the equals sign and figure out the type for me."

Cleaning up the noise in a Loyalty Tracker

Let's build a quick little utility that tracks loyalty points for customers. I want to store a map where the key is the customer's name and the value is a list of their individual transaction amounts. Traditionally, that declaration is a nightmare to look at.

public void processLoyaltyPoints() {
    // The old, verbose way
    Map<String, List<Integer>> customerTransactions = new HashMap<>();
    
    customerTransactions.put("Alice", new ArrayList<>());
    customerTransactions.get("Alice").add(100);
    customerTransactions.get("Alice").add(50);
}

Now, let's use var. Since the compiler sees new HashMap<>(), it knows exactly what customerTransactions is. I don't need to repeat the generics.

public void processLoyaltyPoints() {
    // Much cleaner
    var customerTransactions = new HashMap<String, List<Integer>>();
    
    customerTransactions.put("Alice", new ArrayList<>());
    customerTransactions.get("Alice").add(100);
}

Notice that I still put the generics on the right side. If I just wrote var map = new HashMap();, Java would infer it as a raw HashMap, and I'd be back to dealing with Object types and compiler warnings. The goal is to remove redundancy, not type safety.

Wait, why isn't this compiling?

As I was sketching this out, I tried to move the customerTransactions map outside the method so it could be shared across the whole class. I did something like this:

public class LoyaltyService {
    var customerTransactions = new HashMap<String, List<Integer>>(); // Error here!

    public void process() {
        // ...
    }
}

And immediately, the IDE started screaming at me. Here is the most important rule about var: it only works for local variables.

You cannot use var for class fields, method parameters, or return types. Why? Because Java wants the "public contract" of your class to be explicit. If another developer uses your LoyaltyService, they shouldn't have to guess what the type of a field is by tracing the initialization logic. I had to move it back inside the method or give it an explicit type if I wanted it as a field.

Knowing when to keep the explicit type

Just because you can use var everywhere doesn't mean you should. I've seen some developers treat it like JavaScript, where every single variable is var. That makes the code a riddle.

Take a look at this:

var result = database.fetchRecords();

If I'm reading this code for the first time, I have no idea what result is. Is it a List? A ResultSet? A custom QueryResponse object? In this case, the "verbosity" of an explicit type is actually a feature—it's documentation. I generally use var when the type is obvious from the constructor (like new ArrayList<>()) or when the variable name makes the type crystal clear (like var userList = ...).




📋 Practical Task

Refactoring the Inventory Report Generator

You are reviewing a piece of code for a warehouse system. The current implementation is cluttered with redundant type declarations, and one developer mistakenly tried to use var where it isn't allowed.

Your task:

  1. Fix the compilation error by providing an explicit type for the class field.
  2. Refactor the local variables inside the generateReport method to use var where it improves readability without sacrificing clarity.
import java.util.*;

public class InventoryReport {
    // TASK 1: Fix this line. var cannot be used for fields.
    var inventoryMap = new HashMap<String, Integer>();

    public void generateReport() {
        // TASK 2: Refactor these local variables to use var
        List<String> itemNames = new ArrayList<>();
        itemNames.add("Widget");
        itemNames.add("Gadget");

        Map<String, Integer> stockLevels = new HashMap<>();
        stockLevels.put("Widget", 10);
        stockLevels.put("Gadget", 20);
        
        System.out.println("Report generated for " + itemNames.size() + " items.");
    }
}
Rating
0 0

There are no comments for now.

to be the first to leave a comment.