Java var Keyword: Local Variable Type Inference
Introduction
Since Java 10, you can declare a local variable with
(Note - This tutorial assumes you know how to declare variables in JavaClick to read tutorial: Variables in Java: Declaration, Initialization and Scope.) How var works With
OUTPUT on compiling the above code
Where var can be used
OUTPUT of the above code
Explanation of the code
OUTPUT on compiling the above code
And for a field -
OUTPUT on compiling the above code
Note - Since Java 11,
Surprises in the inferred type
OUTPUT of the above code
Explanation of the code
var instead of writing its type, and let the compiler work the type out. This is called local variable type inference. This tutorial explains the var keyword in Java with examples. We will start with how var works, and why a var variable is still strongly typed. We will then see where var can be used, and the places where it cannot. Next we will look at some surprises in the types var infers. Lastly, we will go through guidelines for using var so that it makes code clearer, not harder to read.(Note - This tutorial assumes you know how to declare variables in JavaClick to read tutorial: Variables in Java: Declaration, Initialization and Scope.) How var works With
var, the compiler looks at the value you initialize the variable with, and gives the variable that value's type. These two declarations produce exactly the same variable -
An explicit type and var
ArrayList<String> names = new ArrayList<String>();
var names = new ArrayList<String>(); // inferred type: ArrayList<String>
var does not make Java dynamically typed. The type is decided once, at compile time, and never changes. Assigning a value of a different type later is a compile error, just as if you had written the type yourself -
A var variable keeps its inferred type
//VarIsStatic.java
public class VarIsStatic {
public static void main(String[] args) {
var count = 10; // inferred as int
count = "ten";
}
}
VarIsStatic.java:5: error: incompatible types: String cannot be converted to int
count = "ten";
^
1 error
var only saves you from writing the type; the compiled code is identical. It is a reserved type name rather than a full keyword, so existing code with a variable or method called var still compiles.
var works for local variables which are initialized when they are declared - in methods and blocks, in for and enhanced for loops, and in try-with-resources statements.
Using var in local variables and loops
//VarDemo.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class VarDemo {
public static void main(String[] args) {
var message = "Hello"; // String
var count = 3; // int
var price = 19.99; // double
var names = new ArrayList<String>(); // ArrayList<String>
names.add("Tom");
names.add("Harry");
var marks = new HashMap<String, List<Integer>>();
marks.put("Tom", List.of(78, 91));
marks.put("Harry", List.of(85, 64));
for (var i = 0; i < count; i++) { // var in a for loop
System.out.print(message + " ");
}
System.out.println();
for (var entry : marks.entrySet()) { // Map.Entry<String, List<Integer>>
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
System.out.println("price is a " + ((Object) price).getClass().getSimpleName());
}
}
Hello Hello Hello Tom -> [78, 91] Harry -> [85, 64] price is a Double
- The biggest win is with long generic types. Without
var, the loop variable would be writtenMap.Entry<String, List<Integer>> entry. var price = 19.99;inferreddouble, the type of the literal19.99. The last line confirms it: the value, boxed as an object, is aDouble. (AHashMapdoes not keep its entries in insertion order, so the names may print in any order.)- With
var, the type is visible on the right-hand side - innew ArrayList<String>()- so writing it on the left would add nothing.
var is not allowed -- without an initializer -
var x; - with
nullas the initializer -var x = null;(nullhas no useful type) - with an array initializer alone -
var nums = {1, 2, 3};(butvar nums = new int[] {1, 2, 3};is fine) - for fields, method parameters and method return types
- for several variables in one declaration -
var a = 1, b = 2;
Local variables where var cannot infer a type
//VarErrors.java
public class VarErrors {
public static void main(String[] args) {
var noValue;
var nothing = null;
var nums = {1, 2, 3};
}
}
VarErrors.java:4: error: cannot infer type for local variable noValue
var noValue;
^
(cannot use 'var' on variable without initializer)
VarErrors.java:5: error: cannot infer type for local variable nothing
var nothing = null;
^
(variable initializer is 'null')
VarErrors.java:6: error: cannot infer type for local variable nums
var nums = {1, 2, 3};
^
(array initializer needs an explicit target-type)
3 errors
var is not allowed for fields
//VarField.java
public class VarField {
var count = 10;
}
VarField.java:3: error: 'var' is not allowed here var count = 10; ^ 1 error
var can also be used for the parameters of lambda expressions, mainly so that annotations can be added to them - for example (@NonNull var s) -> s.length().
var infers the exact type of the initializer, which is not always the type you would have written -
Inferred types that may surprise you
//VarSurprises.java
import java.util.ArrayList;
import java.util.List;
public class VarSurprises {
public static void main(String[] args) {
var small = 10; // int, not long or byte
var big = 10L; // long
var ratio = 10f; // float
var initial = 'T'; // char, not String
var list = new ArrayList<>(); // ArrayList<Object> - the diamond has nothing to infer from
list.add("Tom");
list.add(42);
System.out.println("list holds anything: " + list);
List<String> typed = new ArrayList<>(); // the declared type tells the diamond what to use
typed.add("Tom");
System.out.println(small + " " + big + " " + ratio + " " + initial + " " + typed);
}
}
list holds anything: [Tom, 42] 10 10 10.0 T [Tom]
- Numeric literals decide the type:
10is anint,10Lalongand10fafloat. If you need alongor abyte, use the suffix or write the type. 'T'in single quotes is achar, not aString.var list = new ArrayList<>()infersArrayList<Object>, which accepts anything and loses type safety. Do not combinevarwith the empty diamond<>- write the type argument, as innew ArrayList<String>().
- Use var when the type is obvious from the right-hand side - a
newexpression, a literal, or a well-named factory method such asLocalDate.now(). - Write the type when it is not obvious. In
var result = process(order);the reader cannot tell whatresultis without looking upprocess(). - Choose good variable names. With
var, the name carries more of the meaning -var customerstells more thanvar list. - Keep scopes small.
varworks best for variables used within a few lines of their declaration.
var lets the compiler infer the type of a local variable from its initializer, and that the variable is still statically typed. We then used var for local variables and loop variables, and saw the places where it is not allowed - without an initializer, with null or a bare array initializer, and for fields, parameters and return types. Next we looked at surprising inferred types, such as int for numeric literals and ArrayList<Object> with the empty diamond. Lastly, we went through guidelines for using var well. In the next tutorial, we start on Java's operators with arithmetic, relational and logical operatorsClick to read tutorial: Java Arithmetic, Relational and Logical Operators.Java Fundamentals Tutorials
Type Conversion and Casting in Java with ExamplesClick to read tutorial: Type Conversion and Casting in Java with Examples Java Arithmetic, Relational and Logical OperatorsClick to read tutorial: Java Arithmetic, Relational and Logical Operators Java Syntax Basics: Statements, Identifiers, KeywordsClick to read tutorial: Java Syntax Basics: Statements, Identifiers, Keywords Variables in Java: Declaration, Initialization and ScopeClick to read tutorial: Variables in Java: Declaration, Initialization and Scope Java Primitive Data Types and Their Ranges with ExamplesClick to read tutorial: Java Primitive Data Types and Their Ranges with Examples Java Literals: Integer, Floating-Point, char and booleanClick to read tutorial: Java Literals: Integer, Floating-Point, char and boolean Java Bitwise and Shift Operators with ExamplesClick to read tutorial: Java Bitwise and Shift Operators with Examples
Type Conversion and Casting in Java with ExamplesClick to read tutorial: Type Conversion and Casting in Java with Examples Java Arithmetic, Relational and Logical OperatorsClick to read tutorial: Java Arithmetic, Relational and Logical Operators Java Syntax Basics: Statements, Identifiers, KeywordsClick to read tutorial: Java Syntax Basics: Statements, Identifiers, Keywords Variables in Java: Declaration, Initialization and ScopeClick to read tutorial: Variables in Java: Declaration, Initialization and Scope Java Primitive Data Types and Their Ranges with ExamplesClick to read tutorial: Java Primitive Data Types and Their Ranges with Examples Java Literals: Integer, Floating-Point, char and booleanClick to read tutorial: Java Literals: Integer, Floating-Point, char and boolean Java Bitwise and Shift Operators with ExamplesClick to read tutorial: Java Bitwise and Shift Operators with Examples