Java 10 – Local Variable Type Inference – JEP 286

Java 10 - Local Variable Type Inference


This article provides details about a Local-Variable Type Inference introduced as a new feature in Java 10. It explains the need for Local-Variable Type Inference and how to use it in your program while using Java 10.

Advertisements

Introduction

We all know that Java is very concern about type safety of variables and instances. The addition of generics in Java 5 strengthens the type safety in Java. But there are many other programming languages like C++, Go, Scala, Kotlin, etc, which infer the type of a variable by itself.

Now with the addition of JEP 286, we have Type Inference in java for local variable declarations with initializers. A thing to keep in mind that Java will still be strong statically typed language. The new feature just allows it to infer the type of local variables at compile time.

The main idea behind introducing this feature is to:

  1. Reduce the boilerplate code
  2. Reduce ceremony associated with the code
  3. Increase code readability

Note: The type inference feature is for local variables only. The compiler will not infer type for instance or class variables.

What is Type Inference?

Type Inference refers to an automatic detection of the data type of a variable/expression.

In Java when we declare any variable, we have to specify it’s data type in the declaration as well as initialization. For example:

BigDecimal bigDecimal = new BigDecimal("123");
String myString = "My String";
Integer myInt = 1234;

StringBuffer stringBuffer;
stringBuffer = new StringBuffer();

In Java 10 using var we no longer need to specify the data type while declaring local variables if we initialize them at the same time. With that said, in Java 10 above code will change as follow:

var bigDecimal = new BigDecimal("123");
var myString = "My String";  // infers as String
var myInt = 1234;            // infers as Integer

var stringBuffer;                  // will NOT compile as not initialized
stringBuffer = new StringBuffer();

In above code, except stringBuffer, every variable is valid and the compiler will infer it’s respective data type.  var stringBuffer; will not compile because we are not initializing it.

“var” a reserved type name

You must be wondering what the word var means in code given in the previous section? It sounds familiar if you already worked in javascript(though no relations with javascript here).

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

You can use var for following things:

  • As local variable name
    • var var = 123;
  • As method name
    • public void var() { }
  • In package name
    • package com.bytestree.core.var;

 

You cannot use var for following things:

  • Class name
  • Interface name
  • Enum name
Advertisements

Local Variable Type Inference Rules

We can use Local Variable Type Inference for:

  1. Local variable declarations with initializers
  2. Enhanced for  loop indexes
  3. For index variable in traditional for  loop

You already know about local variable declarations with initializers given in the previous section. Now check how to use Local Variable Type Inference in for  loop:

var integerList = Arrays.asList(1, 2, 3, 4);

// enhanced for loop indexes
for (var number : integerList) {
	System.out.println(number);
}

// traditional for loop index (i)
for (var i = 0; i < integerList.size(); i++) {
	System.out.println(integerList.get(i));
}

In above example, you also see how var is used for Collections.

Examples of Type Inference

With above three cases, following are also valid uses of Local Variable Type Inference:

Diamond Operator

var list = new ArrayList<>();   // List of Objects

In above code, due to the absence of left-hand side details, the compiler cannot infer the exact type of data in ArrayList, so it infers to supertype which is Object. Though you can use diamond operator here, it’s better to avoid it and specify the type on the right-hand side for better readability of code and correct inference like given below:

var listOfString = new ArrayList<String>();

Stream

Use of var for the stream is perfectly valid.

var stream = list.stream();

Anonymous Class

Variables can have Anonymous class type.

var inner = new Thread() {
	@Override
	public void run() {
		System.out.println("Running Thread");
	}
};
inner.start();

Examples of Limitations of Type Inference

Following are the incorrect ways or limitations of using local variable type Inference and var reserved type name:

Without Initializer or initialize with null

var withoutInitializer;
var initializeToNull = null;

Both lines in above code will give compilation error “cannot infer type for local variable…

Multiple variable instantiations

You cannot instantiate multiple var variables at the same time as given  below:

var a = "a", b = "b";

Lambda Expressions initializer

There are no type details on the right-hand side, due to which you cannot use lambda expression initializer.

var x = () -> { };

Method Reference initializer

You cannot use method reference initializer like the following code. You will get an error message: method reference needs an explicit target-type

var integerFunction = Integer::intValue;

Array Initializer

You cannot initialize an array like given below:

var numbers[] = {1, 2, 3, 4};

The correct way of initializing an array with var is:

var numbersRight = new int[]{1, 2, 3, 4};

var in the method signature

You cannot use var in the method signature, therefore you cannot use it as a return type or method parameter.

private var varInSignature(var value) {
        return null;
}
Advertisements

Source Code

All code used to test Type Inference given above is available in GitHub.

Hope this article has given you details about what Local Variable Type Inference is and how to use it in your code. For any questions or suggestions, please leave a comment.