Java Local Variable Type Inference examples

In this post:

  • what is Local Variable Type Inference
  • examples
  • when is useful
  • what is not allowed

Short video tutorial: java local variable type inference examples

Java 10 and Local Variable Type Inference

Since Java 10 new feature is added - Local Variable Type Inference - or shortly as code examples:

Integer Example

var x = 5 //inferred to be type int

checking the type by:

System.out.println(((Object)x).getClass().getName());

result:

java.lang.Integer

this is the wrapper Integer of the primitive int

String Example:

jshell> var y = "f";
y ==> "f"

checking the type by:

jshell> y.getClass().getName()
$5 ==> "java.lang.String"

result:

java.lang.String

Collection Example:

This is very useful for shortening and making Java more concise about the syntactic burden that is part of Java since it's early versions. Of course some people may be concerned about how accurate the infer is working. In the example below we see collections:

var list = new ArrayList<String>();  // infers ArrayList<String>
var stream = list.stream();          // infers Stream<String>

Can you change the type

Yes you can change the type of local variable with type inference but this could be misleading and maybe a bad practice:

jshell> var n = 0
n ==> 0

jshell> var n = "a"
n ==> "a"

jshell> var n = 1.0
n ==> 1.0

Have in mind that this can be removed from future versions of Java.

What is var?

Var is reserved type name ( and not a keyword as many could think of). You can consider var as a special type.

What else is new in java 10:
How to install Java 10 and what's new

Examples

For loop

The first example to come to mind is loop for:

for (var x=0; x<6; x++) { System.out.print(x); }

result:

012345

or for other numeric formats:

for (var x=0.0; x<10.0; x+=0.5) { System.out.print(x + "; "); }

result:

0.0; 0.5; 1.0; 1.5; 2.0; 2.5; 3.0; 3.5; 4.0; 4.5; 5.0; 5.5; 6.0; 6.5; 7.0; 7.5; 8.0; 8.5; 9.0; 9.5;

Collections

Initialization of collections now it's easier and shorter:

Map<String,Integer> mixedMap = new HashMap <> ();
Map<String,String> stringMap = new HashMap <> ();
Map<String,String> intMap = new HashMap <> ();
var mapInfer = new HashMap <String,String> ();
var mapSimple = new HashMap <> ();

Let's add some values to mapSimple and print the result:

mapSimple.put("a","b")
mapSimple.put(1,1)
mapSimple.forEach((key, value) -> System.out.printf("%s %s%n", key, value));

result:

a b
1 1

More about maps: Java map examples

We can do also:

var a = 1;
var b = "h";
mapSimple.forEach((key, value) -> System.out.printf("%s %s%n", key, value));

result:

1 h

Note: that even a is from type int finally is converted to String.

Local Variable Type Inference what is not allowed

No multiple variables yet

var a=1,b=0;

this gives an error:

Error:
'var' is not allowed in a compound declaration
var a=1,b=0;

Assign null

In Java you can declare and initialize variable as:

jshell> String x = null
x ==> null

but you can't use it with type inference:

jshell> var x = null
|  Error:
|  cannot infer type for local variable x
|    (variable initializer is 'null')
|  var x = null;
|  ^-----------^

Declaration only

In order to use inference of local variables you should also initialize them:

jshell> var x;
|  Error:
|  cannot infer type for local variable x
|    (cannot use 'var' on variable without initializer)
|  var x;
|  ^----^

No Array Initializers, Lambdas, Method References, no method return type or parameters

  1. No Array Initializers

For example you can initialize array in Java with:

int[] data = {10,20,30,40,50,60,71,80,90,91};

but if you try this with local variable inference you will get an error:

jshell> var data = {10,20,30,40,50,60,71,80,90,91};
|  Error:
|  cannot infer type for local variable data
|    (array initializer needs an explicit target-type)
|  var data = {10,20,30,40,50,60,71,80,90,91};
  1. No lambdas with type inference:

You can't use:

var runner = () -> { System.out.println("Hello World!"); };

You should always use:

Runnable runner = () -> { System.out.println("Hello World!"); };

Otherwise error is raised:

|  cannot infer type for local variable runner
|    (lambda expression needs an explicit target-type)
  1. No method References

You can't use:

var show = MethodReference::showAge;

Because of error:

| cannot infer type for local variable show
| (method reference needs an explicit target-type)

You need to use:

Consumer<Integer> show = MethodReference::showAge;

full example

public class MethodReference {
    public static void main(String[] args) {
        Consumer<Integer> show = MethodReference::showAge;
    }
    public static void showAge(Integer x) {
        System.out.println(x);
    }
}
  1. no type inference for method parameters or return types:
public var readMe(var str1, var str2) {
    return str1 + str2;
}

Or you will get compilation error:

| 'var' is not allowed here
| public var readMe(var str1, var str2) {
| -

You need to provide them explicitly:

public String readMe(String str1, String str2) {
    return str1 + str2;
}