Local Type Variable Inference in Java

Local type variable inference in Java (Sherlock Holmes image with magnifying glass looking at var keyword)

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!

Leave a Comment

Your email address will not be published. Required fields are marked *

Code like a Java Guru!

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email info@incusdata.com

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.

Your Java tip is on its way!

Check that incusdata.com is an approved sender, so that your Java tips don’t land up in the spam folder.

Our privacy policy means your data is safe. You can unsubscribe from these tips at any time.