Local Variable Type Inference in Java 11 simplifies the syntax used to declare local variables. With the introduction of the var
keyword, you can now declare a variable without specifying its explicit type, which the compiler infers from the context.
var
“.int a = 5; var b = 3; var sum = a + b;
var
The var
keyword enables you to write more concise and readable Java code. This feature is especially useful in reducing the verbosity of your Java code, making it easier to read and maintain.
Before Java 11:
BufferedReader reader = new BufferedReader(new FileReader("data.txt")); String line = reader.readLine();
List<LocalDate> dates = Arrays.asList(LocalDate.of(2022, 1, 1), LocalDate.of(2022, 12, 31)); for (LocalDate date : dates) { System.out.println(date); }
AnIncrediblyLongInterfaceName foobar = new AnIncrediblyLongImplementationName();
After Java 11:
var reader = new BufferedReader(new FileReader("data.txt")); var line = reader.readLine();
var dates = Arrays.asList(LocalDate.of(2022, 1, 1), LocalDate.of(2022, 12, 31)); for (var date : dates) { System.out.println(date); }
var lorem = new AnIncrediblyLongImplementationName();
var
var
can only be used when the variable is declared and initialised in the same statement; the compiler must be able to infer the type from the initial value.var a = 5; // ✅ var b; // ❌ b = 5;
var
is only permitted for local variables inside methods or blocks. It cannot be used for member variables, method parameters, or return types.public class Person { private String firstName; private var lastName; // ❌ public String getFullName(){ var fullName = firstName + " " + lastName; // ✅ return fullName; } public var getFirstName(){ // ❌ return firstName; } public void setFirstName(var firstName){ // ❌ this.firstName = firstName; } }
var
cannot be used with null
initialization without a type hint, as the compiler cannot infer the type.var personA = null; // ❌
var
with arrays, the type and dimensions should be clear from the context. You cannot use var
for anonymous arrays without explicit type.var names = new String[]{"Adam", "Bill", "Chris"}; // ✅ var fruits = {"Apple", "Banana", "Cherry"}; // ❌
Questions:
Which of the following statements about the var
keyword in Java 11 is true?
A) var
can be used to declare both local variables and class fields.
B) var
requires an initializer to infer the variable type.
C) var
allows for declaring multiple variables of different types in a single statement.
D) var
can be used to declare a method’s return type.
var
(or using an explicit type if var
wouldn’t work) in the given Java code snippet:____ numbers = List.of(1, 2, 3, 4, 5); ____ stream = numbers.stream(); for (____ num : numbers) { System.out.println(num); }
The following Java code snippet using var
has multiple issues. Identify and correct them to make the code compile and run successfully.
var x; x = 10; var list = null; list = new ArrayList<String>(); var map = new HashMap<>(); map.put("key", "value");
var
In Our Own CodeVarDemo
-class in which you declare the following variables using var
:'j'
.LocalDateTime
set to the current time.NameGenerator
-class, write a method named “generateNames()
” that returns a collection of names as a Collection<String>
.ArrayList
, HashSet
or PriorityQueue
.main
-method of VarDemo
, use var
to store the collection returned by your method.var
for the loop’s local variable) to print each name in the list.data
” directory if it doesn’t exist, and then write the names in the collection to a text file named “vars.txt
“, using var
wherever possible.var
requires an initializer to infer the variable type.var numbers = List.of(1, 2, 3, 4, 5); var stream = numbers.stream(); for (var num : numbers) { System.out.println(num); }
var x; x = 10; var list = null; list = new ArrayList<String>(); var map = new HashMap<>(); map.put("key", "value");
var x = 10; var list = new ArrayList<String>(); var map = new HashMap<String, String>(); map.put("key", "value");
var x
: var needs initialization at the point of declaration.var list
: Cannot use var with null without a type hint.var map
: Specify the type on the right-hand side for clarity and type inference.var
In Our Own Codepublic class NameGenerator { public static Collection<String> generateNames(){ var names = new String[]{"Adam", "Billy", "Cheryl"}; switch (new Random().nextInt(3)){ case 0: return new ArrayList<>(List.of(names)); case 1: return new HashSet<>(List.of(names)); case 2: return new PriorityQueue<>(List.of(names)); default: throw new IllegalStateException("Unexpected number generated."); } } }
public class VarDemo { public static void main(String[] args) { // 1. var integer = 10; var doubleValue = 3.1415; var character = 'j'; var booleanValue = true; var now = LocalDateTime.now(); // 2. & 3. var names = NameGenerator.generateNames(); // 4. System.out.printf("The collection in the var is a %s.\n", names.getClass().getSimpleName()); // 5. names.add("Java"); // 6. for (var name : names) { System.out.println(name); } // 7. var path = Path.of("data", "vars.txt"); try { if(Files.notExists(path)){ Files.createDirectories(path.getParent()); } } catch (IOException e) { throw new RuntimeException(e); } try ( var writer = new FileWriter(path.toFile()); var bufferedWriter = new BufferedWriter(writer); ){ for (var name : names) { bufferedWriter.write(name); bufferedWriter.newLine(); } } catch (IOException e){ e.printStackTrace(); } } }
var
for Lambda ParametersJava 11 also allows you to use var
for lambda parameters, making it consistent with local variables.
Before:
List<String> fruits = List.of("Apple", "Banana", "Cherry"); fruits.forEach((String f) -> System.out.println(f)); List<Integer> primeNums = List.of(2, 3, 5, 7, 11); int product = primeNums.stream().reduce(1, (Integer a, Integer b) -> a * b);
javaCopy codeComparator<String> comparator = (String first, String second) -> first.length() - second.length();
After:
List<String> fruits = List.of("Apple", "Banana", "Cherry"); fruits.forEach((var f) -> System.out.println(f)); List<Integer> primeNums = List.of(2, 3, 5, 7, 11); int product = primeNums.stream().reduce(1, (var a, var b) -> a * b);
var
for Lambda Parametersvar
for one parameter in a lambda, you must use it for all parameters in that lambda.var
, you can’t then randomly use explicit types too.var
in lambda parameters, you must include parentheses around the parameters.var
for Lambda Parameters?Lambda syntax already allows us to write ultra-concise code, even letting us omit data types for the parameters, which begs the question: why bother with var
then?
BiFunction<String, String, Integer> longF = (String s1, String s2) -> Integer.parseInt(s1) + Integer.parseInt(s2); BiFunction<String, String, Integer> shortF = (var s1, var s2) -> Integer.parseInt(s1) + Integer.parseInt(s2); // Why ??? BiFunction<String, String, Integer> shorterF = (s1, s2) -> Integer.parseInt(s1) + Integer.parseInt(s2);
var
in lambda parameters is to enable the use of annotations.var
, you can annotate each parameter, which is crucial for functionalities like non-null validation, debugging, or other custom behaviours, while still keeping it short.Function<LocalDateTime, String> longF = (@NonNull LocalDateTime dt) -> dt.getDayOfWeek().name(); // ✅ Function<LocalDateTime, String> shortF = (@NonNull var dt) -> dt.getDayOfWeek().name(); // ✅ and shorter Function<LocalDateTime, String> shorterF = @NonNull dt -> dt.getDayOfWeek().name(); // ❌
var
in the lambda expression to sum up all elements of a list.List<Integer> numbers = List.of(5, 10, 15); int sum = numbers.stream().reduce(0, (____, ____) -> ___ + ___);
Correct the following code snippet which incorrectly uses var
with lambda parameters.
List<String> words = List.of("hello", "world", "java", "stream"); String combined = words.stream().reduce("", (var wordA, String wordB) -> wordA + wordB);
Function<Integer, String> convert = @Debug var num -> String.valueOf(num);
List<Integer> numbers = List.of(5, 10, 15); int sum = numbers.stream().reduce(0, (var a, var b) -> a + b);
List<String> words = List.of("hello", "world", "java", "stream"); String combined = words.stream().reduce("", (var wordA, String wordB) -> wordA + wordB);
Function<Integer, String> convert = @Debug var num -> String.valueOf(num);
List<String> words = List.of("hello", "world", "java", "stream"); String combined = words.stream().reduce("", (var wordA, var wordB) -> wordA + wordB);
Function<Integer, String> convert = (@Debug var num) -> String.valueOf(num);
var
: Java 11 introduces var
, allowing automatic type inference for local variables, making code less verbose and enhancing readability by removing explicit type declarations where the context makes them obvious.var foo = new AnIncrediblyLongNameForAClass();
var
must be initialized upon declaration to enable type inference. var
is restricted to local variable declarations within methods or code blocks.var
for Class Fields or Return Types: Usage of var
is limited to local variables inside methods; it cannot be used for class fields, method parameters, or return types.var
in lambda parameters, it requires all parameters to be either declared with var
or none at all, and parentheses are mandatory.var
in lambda parameters allows for the application of annotations, offering enhanced control and additional functionality like non-null checks, which is not possible with implicitly typed lambda expressions.