We all generally enjoy coding in Java, otherwise you probably wouldn’t be reading these posts.
However, sometimes coding can get a bit repetitive. We often find ourselves typing lots of “boilerplate code”. This happens particularly when creating generic typed variables and fields.
Type Inference from Java 7
From Java 5, when we wanted to instantiate a generic object, we needed to include the type argument in the variable declaration as well as in the constructor, as follows:
List<Employee> emps = new ArrayList<Employee>();
Map<<String>, <List<String>> map = new HashMap<<String>, <List<String>>();
Fortunately from Java 7 this verbosity was removed. We can now leave out the type arguments when calling the constructor of a generic class, and can replace them with an empty set of type parameters (<>
). We can do this as long as the compiler can infer the type arguments from the way we use it. The previous code snippet can now be replaced with much cleaner looking code:
List<Employee> emps = new ArrayList<>();
Map<<String>,<List<String>> map = new HashMap<>();
The pair of angle brackets is called the type inference operator, or more informally, the diamond operator.
Local Variable Type Inference from Java 10
Type inference goes some way towards reducing the verbosity of the Java language. However, we still have to indicate some sort of typing on both sides of the equals (=
) sign when using generic types.
Java 10 added local-variable type inference. This allows local variable declarations as follows:
var emps = new ArrayList<Employee>(); // this infers emps is ArrayList<Employee>
var stream = emps.stream(); // this infers stream is Stream<Employee>
One of the other benefits of local variable type inference is that we don’t necessarily have to think quite so hard. Contrast the next two snippets of code. The first uses explicit type declarations, the second uses type inference:
Path path = Paths.get(fileName);
List<String> lines = Files.readAllLines(path);
The following code is even easier and almost as obvious:
var path = Paths.get(fileName); // this infers that path is of type Path
var lines = Files.readAllLines(path); // this infers that lines is of List<String>
This again reduces some of the verbose programming we have to do, but still gives us the static type safety of Java.
What is var?
The identifier var
is not a keyword. It is a reserved type name. This means that we’re allowed to use var
as a variable, method, or package name, but not allowed to use it as a class or interface name.
This is only allowed for local variables with initializers, and not for class or instance variables (fields). We can also use it for local variables the we declare in a for-loop, and for the indexes in the enhanced for-loop.
There are other forms of local variable declarations that are not allowed. These are:
- Variables without initializers.
- Variables initialized with
null
. - Declarations of multiple variables.
- Variables with extra array dimension brackets.
- Variables that reference the variable being initialized.
Using var
for field declarations, constructor and method formal parameters, method return types, or formal parameters of catch
statements is not allowed.
Local Variable Syntax for Lambda Parameters from Java 11
Java 11 added local-variable syntax for lambda parameters. This allows us to use var
when we declare the formal parameters of implicitly typed lambda expressions, as follows:
(var a, var b) -> a.foo(b) // implicitly typed lambda expression
is the same as:
(a, b) -> a.foo(b)
Using var
in this way is similar to the syntax of local variable declarations.
The use of var
is only allowed for formal parameters of implicitly typed lambda expressions. We must either use var
for all the formal parameters or for none of them.
If we use explicit types in lambda expressions, we need to declare the types of all the formal parameters. We can’t use explicit types for some formal parameters and var
for others.
Ending Off
For more details on JEP 286: Local-Variable Type Inference, see https://openjdk.org/jeps/286
For more details on JEP 323: Local-Variable Syntax for Lambda Parameters, see https://openjdk.org/jeps/323
Don’t forget to share your comments and Java experiences.
Stay safe, and I’ll see you next week!