78. Simple var example

Starting with version 10, Java comes with JEP 286, or Java LVTI, also known as the var type.

The var identifier is not a Java keyword, it is a reserved type name.

This is a 100% compile feature with no side effects in terms of bytecode, runtime, or performance. In a nutshell, LVTI is applied to local variables and works as follows: the compiler checks the right-hand side and infers the real type (if the right-hand side is an initializer, then it uses that type).

This feature ensures compile-time safety. This means that we cannot compile an application that tries to achieve a wrong assignment. If the compiler has inferred the concrete/actual type of var, we can only assign the values of that type.

There are multiple benefits of LVTI; for example, it reduces code verbosity and mitigates redundancy and boilerplate code. Moreover, the time spent to write code can be reduced by LVTI, especially in cases that involve heavy declarations, as follows:

// without var
Map<Boolean, List<Integer>> evenAndOddMap...

// with var
var evenAndOddMap = ...

A controversial benefit is represented by code readability. Some voices sustain that using var reduces code readability, while other voices support the opposite. Depending on the use case, it may require a trade-off in readability, but the truth is that, typically, we pay a lot of attention to meaningful names for fields (instance variables) and we neglect the names of local variables. For example, let's consider the following method:

public Object fetchTransferableData(String data)
throws UnsupportedFlavorException, IOException {

StringSelection ss = new StringSelection(data);
DataFlavor[] df = ss.getTransferDataFlavors();
Object obj = ss.getTransferData(df[0]);

return obj;
}

This is a short method; it has a meaningful name and a clean implementation. But checkout the local variables' names. Their names are drastically reduced (they are just shortcuts), but this is not a problem since the left-hand side provides enough information that we can easily understand the type of each local variable. Now, let's write this code using LVTI:

public Object fetchTransferableData(String data)
throws UnsupportedFlavorException, IOException {

var ss = new StringSelection(data);
var df = ss.getTransferDataFlavors();
var obj = ss.getTransferData(df[0]);

return obj;
}

Obviously, the code's readability has decreased since it's now harder to infer the type of the local variables. As the following screenshot reveals, the compiler doesn't have a problem with inferring the correct types, but for humans, this is a lot more difficult:

The solution to this problem consists of providing a meaningful name to local variables when relying on LVTI. For example, the code can regain its readability if the local variables' names are provided, as follows:

public Object fetchTransferableData(String data)
throws UnsupportedFlavorException, IOException {

var stringSelection = new StringSelection(data);
var dataFlavorsArray = stringSelection.getTransferDataFlavors();
var obj = stringSelection.getTransferData(dataFlavorsArray[0]);

return obj;
}

Nevertheless, the readability problem is also caused by the fact that, typically, we tend to look at the type as primary information and the variable name as secondary information, while this should be the opposite.

Let's look at two more examples that are meant to enforce the aforementioned statements. A method that uses collections (for example, List) is as follows:

// Avoid
public List<Player> fetchPlayersByTournament(String tournament) {

var t = tournamentRepository.findByName(tournament);
var p = t.getPlayers();

return p;
}

// Prefer
public List<Player> fetchPlayersByTournament(String tournament) {

var tournamentName = tournamentRepository.findByName(tournament);
var playerList = tournamentName.getPlayers();

return playerList;
}

Providing meaningful names for local variables doesn't mean falling into the over-naming technique.

For example, avoid naming variables by simply repeating the type name:

// Avoid
var fileCacheImageOutputStream​
= new FileCacheImageOutputStream​(..., ...);

// Prefer
var outputStream​ = new FileCacheImageOutputStream​(..., ...);

// Or
var outputStreamOfFoo​ = new FileCacheImageOutputStream​(..., ...);
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset