• Software
  • Leadership
  • Agile
  • Events
  • Other Topics
    • Finance
    • Robotics & AI
    • System Administration
    • Books
    • Life Experiences
    • Environment
  • Write and Earn
  • About Us
    • About Us
    • Our Contributors
    • Contact Us
    • Article Submission Guidelines
    • Logo demystified
  • Follow @MeJaneve
    Janeve.Me
  • Categories

    Browse through following categories for articles written by professionals.
    • Agile
      4
    • Books
      5
    • Environment
      1
    • Events and Conferences
      7
    • Featured
      15
    • Finance
      1
    • Leadership
      5
    • Life Experiences
      8
    • Software
      30
    • System Administration
      2
  • Software
  • Leadership
  • Agile
  • Events
  • Other Topics
    • Finance
    • Robotics & AI
    • System Administration
    • Books
    • Life Experiences
    • Environment
  • Write and Earn
  • About Us
    • About Us
    • Our Contributors
    • Contact Us
    • Article Submission Guidelines
    • Logo demystified
Home » Software

Local Variable Type Inference in Java 10

Janeve George Posted On April 25, 2020
0
751 Views


0
Shares
  • Share On Facebook
  • Tweet It

Type Inference is the ability of a programming language to automatically detect the data type of an expression or variable declarations. Type inference is a common concept you would find in modern programming languages. It is often a characteristic of functional programming languages.

In Java type inference was first introduced through generics type inference in Java 7. This refers to the ability to understand the diamond operator <>. E.g:

List<Stirng> list = new ArrayList<>();

Here the diamond operator <> is inferred as String.

Local Variable Type Inference

Java 10 has enhanced the language specification by introducing ‘local variable type inference’. Java traditionally has a problem with a higher degree of boilerplate coding that is required as compared to other languages. The motivation behind the enhancements in the type inference is to improve the language to reduce these boilerplate coding to some extent.

A simple example

For example, prior to Java 10, local variables are initialized as shown below.

//String variable
String name = "Janeve George";

// Initializing object
StringBuilder stringBuilder = new StringBuilder();
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yy");

//Initialization with Generic types
List<String> list = new ArrayList<>();

The issue with these statements is that the left-hand side seems to be redundant. The right-hand side of the expression makes it clear what type we are expecting. The local variable type inference in Java 10 helps the programmer not to worry too much on the left-hand side of the expression. The above code can be written with local variable type inference using the var keyword.

//String variable
var name = "Janeve George";

// Initializing object
var stringBuilder = new StringBuilder();
var dateFormat = new SimpleDateFormat("dd/MM/yy");

//Initialization with Generic types
var list = new ArrayList<String>();

A more complex example

Let us take a more complex scenario so that we can appreciate the benefits of the local variable type inference. Let us consider an example class ComplexExampleBeforeJava10:

public class ComplexExampleBeforeJava10 {

    static final Random randomGenerator = new Random();
    static final NumberFormat numberFormatter = NumberFormat.getIntegerInstance();

    public static void main(String[] args) {
        List<HashMap<String, Integer>> list = new ArrayList<>();

        for (int i = 1; i <= 50; i++) {
            list.add(getItem(i));
        }

        Stream<HashMap<String, Integer>> stream = list.stream();
        int length = list.size();
        List<HashMap<String, Integer>> subList = list.subList(10, 20);
        HashMap<String, Integer> map =  list.get(10);
        Set<String> keys = map.keySet();

        // Usages of local variables.
        Integer wrapperInteger = length;
        stream.forEach(System.out::println);
        int subListSize = subList.size();
        int noOfKeys = map.size();
        keys.add("New String");
    }

    private static HashMap<String, Integer> getItem(int numOfElements) {
        HashMap<String, Integer> map = new HashMap<>(numOfElements);
        for (int i = 0; i < numOfElements; i++) {
            int number = randomGenerator.nextInt();
            map.put(numberFormatter.format(number), number);
        }
        return map;
    }

}

Observe the highlighted lines 13-17. The developer will have to make more effort in writing this section. The developer will have to manually evaluate the expression while coding and declaring the local variable with an appropriate type.

The Local Variable Type Inferrence capability in Java 10 improves readability and productivity. The above code can be written as follows using the local variable type inference.

public class ComplexExampleJava10 {

    static final Random randomGenerator = new Random();
    static final NumberFormat numberFormatter = NumberFormat.getIntegerInstance();

    public static void main(String[] args) {
        var list = new ArrayList<HashMap<String, Integer>>(); // inferred as ArrayList<HashMap<String, Integer>>

        for (int i = 1; i <= 50; i++) {
            list.add(getItem(i));
        }

        // Benefits of Local Variables Type Inference show below
        var stream = list.stream();         // inferred as Stream<HashMap<String, Integer>>
        var length = list.size();           // inferred as int
        var subList = list.subList(10, 20); // inferred as List<HashMap<String, Integer>>
        var map =  list.get(10);            // inferred as HashMap<String, Integer>
        var keys = map.keySet();            // inferred as Set<String>

        // Usages of local variables.
        Integer wrapperInteger = length;        // length is considered as int
        stream.forEach(System.out::println);    // forEach of Stream<HashMap<String, Integer>> invoked
        int subListSize = subList.size();       // size of List<HashMap<String, Integer>> invoked
        int noOfKeys = map.size();              // size of HashMap<String, Integer> invoked
        keys.add("New String");                 // add of Set<String> invoked
    }

    private static HashMap<String, Integer> getItem(int numOfElements) {
        HashMap<String, Integer> map = new HashMap<>(numOfElements);
        for (int i = 0; i < numOfElements; i++) {
            int number = randomGenerator.nextInt();
            map.put(numberFormatter.format(number), number);
        }
        return map;
    }

}

Rules for using the ‘var’ keyword

There are some valid and invalid ways of using the var keyword and local variable type inference. The rules for using the var keyword are as follows:

  • It can be used within static and instance blocks within a class.
  • It can be used for a local variable initialization.
  • It can be used for declaring the index variable in the for-loop.
  • It can be used for declaring the iteration variable in the enhanced for-loop.
  • It cannot be used for declaring class properties.
  • It cannot be used for local variables without initialization.
  • It cannot be used for method parameter variables.
  • It cannot be used for a method return type.
  • It cannot be used for local variables which are initialized with null in the right-hand side of the expression.
  • It cannot be used with an array initializer without any explicit target-types.
  • It cannot be used for lambda expressions without any explicit target-types.
public class InvalidUseOfVarKeyword {

    // INVALID - It cannot be used for declaring class properties.
    var classProperty;

    // INVALID - It cannot be used for declaring class properties.
    var dateProperty = new Date();


    public void aMethod(){
        // INVALID - It cannot be used for local variables without initialization.
        var localVariable;


        // INVALID - It cannot be used for local variables which are initialized with null.
        var nullVariable = null;


        // INVALID - It cannot be used with an array initializer without explicit target-types.
        var arrayVariable = {1, 2, 3};

        // The code below is valid since it has an explicit target-type int[]
        var intArrayVariable = new int[]{1, 2, 3}; 
    }

    // INVALID - It cannot be used for method parameter variables.
    public void aMethodWithParameters   (String param1, var param2) {

    }

    // INVALID - It cannot be used for a method return type.
    public var aMethodWithReturnType{ return "Hello"; }

}

You can find all the source code in my github repository.

 

Post Views: 751
0
Shares
  • Share On Facebook
  • Tweet It




Author

Janeve George

A Technology Leader, Software Engineer, and Agile Methodologies enthusiast. Currently, working as Lead Software Development with Zeta Suite. He has more than 1.6 decades of experience spanning different verticals predominated by hosting, cloud, and media delivery technologies.

The Java Concurrency Framework
Read Next

The Java Concurrency Framework

  • Follow @MeJaneve
    Janeve.Me
  • Categories

    Browse through following categories for articles written by professionals.
    • Agile
      4
    • Books
      5
    • Environment
      1
    • Events and Conferences
      7
    • Featured
      15
    • Finance
      1
    • Leadership
      5
    • Life Experiences
      8
    • Software
      30
    • System Administration
      2

  • Popular Posts

  • Recent Posts

    • Java Asynchronous Programming using CompletableFuture - Part 1
    • The Java Stream API
    • Functional Interfaces in Java
    • Online Webinar: Students & New Technology - 28th July 2020
  • Keep In Touch

    Follow us on social media to get latest articles on Programming, System Architecture, Agile Development Methodologies, Product and Project Management, Personal Development, BigData, Robotics, Upcoming Events and more...


Copyright © 2020 | Janeve.Me. All rights Reserved.
Press enter/return to begin your search