Java10 series (ii) Local-Variable Type Inference



This article mainly interprets the Local-Variable Type Inference of java10.


    public void testVar(){
        var list = List.of(1,2,3,4,5);
        var strList =
                .map(e -> "hello" + e)
        var result =

    public void testVarInForEach(){
        var data = Map.of("k1",1,"k2",2,"k3",3,"k4",4,"k5",5);
        for(var entry : data.entrySet()){
            System.out.println(entry.getKey() + ":" + entry.getValue());

    public void testVarInTry() throws IOException {
        try(var input = this.getClass().getClassLoader().getResourceAsStream("demo.txt")) {
            int data =;
            while(data != -1){
                System.out.print((char) data);
                data =;

Var was introduced only to simplify the code. Note that var can only be used for local variables. It cannot be used for class member variables, method parameters, etc.

Style Guidelines

The introduction of var is a double-edged sword. on the one hand, it simplifies the code, but at the same time it may affect the readability, especially those types you are not familiar with. For this reason Stuart W. Marks gave a guide to useStyle Guidelines for Local Variable Type Inference in Java. The main points are as follows:

Main principles

  • Reading code is more important than writing code.
  • Using var should enable readers to clearly infer the type
  • Code readability should not depend on IDE
  • Explicit type is a compromise, although sometimes lengthy, but the type is clear

Var usage guide

  • Variable names should provide useful information
List<Customer> x = dbconn.executeQuery(query);
var custList = dbconn.executeQuery(query);
  • Minimize the scope of local variables
var items = new HashSet<Item>(...);

// ... 100 lines of code ...

for (var item : items) ...

Var’s declaration is too far from being used, and it is not easy to see the type of items clearly.

  • Consider providing sufficient information to readers when var initialization
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

var outputStream = new ByteArrayOutputStream();

For example, on the right is the display type, which is very clear.

  • Expressions for decomposing links or nesting using var local variables
Map<String, Long> freqMap =
                                   .collect(groupingBy(s -> s, counting()));
Optional<Map.Entry<String, Long>> maxEntryOpt = freqMap.entrySet()

You can declare intermediate variables with var

var freqMap =
                     .collect(groupingBy(s -> s, counting()));
var maxEntryOpt = freqMap.entrySet()
  • Be careful with diamond syntax and generics
// OK: both declare variables of type PriorityQueue<Item>
PriorityQueue<Item> itemQueue = new PriorityQueue<>();
var itemQueue = new PriorityQueue<Item>();

// DANGEROUS: infers as PriorityQueue<Object>
var itemQueue = new PriorityQueue<>();

// DANGEROUS: infers as List<Object>
var list = List.of();

// OK: itemQueue infers as PriorityQueue<String>
Comparator<String> comp = ... ;
var itemQueue = new PriorityQueue<>(comp);

// OK: infers as List<BigInteger>
var list = List.of(BigInteger.ZERO);
  • Be careful when declaring strings/numbers using var
boolean ready = true;
char ch = '\ufffd';
long sum = 0L;
String label = "wombat";

var ready = true;
var ch    = '\ufffd';
var sum   = 0L;
var label = "wombat";

byte flags = 0;
short mask = 0x7fff;
long base = 17;

// DANGEROUS: all infer as int
var flags = 0;
var mask = 0x7fff;
var base = 17;

float f = 1.0f;
double d = 2.0;

var f = 1.0f;
var d = 2.0;


Var is a double-edged sword. On the one hand, it can simplify complicated codes. However, improper use will affect the readability of codes, which requires careful use.