Tuesday, March 27, 2018

Finally, Java 10 has var to declare Local Variables - JDK 10 New Feature

Hello guys, In this series of new features of Java 10 articles, today,s I am going to talk about probably the most popular and most useful, the introduction of var keyword (well, it's not really a keyword but I'll you later about it) in Java. If I am not wrong, this feature was supposed to come on Java 9 but dropped later. Finally, Java also has var keyword to declare variables which allows you to declare a variable without their type e.g. instead of doing String str = "Java" you can now just say var str = "Java". This may not sound much gain when declaring String or an int variable but consider about complex types with generics, this will surely save a lot of typing and also improves the readability of code.

Java developers have long been complaining about boilerplate code and ceremonies involved while writing code. Many things which take just 5 minutes in languages like Python, Groovy, or JavaScript can take more than 30 minutes in Java due to its verbosity.

If you have coded in Scala, Kotlin, Go, C# or any other JVM language then you know that they all have some kind of local variable type inference already built into the language.

For example, JavaScript has let and var, Scala and Kotlin have var and val, C++ has the auto, C# has var and Go support this by declaration with the := operator.

Until Java 10, Java was the only language which didn't have local variable type inference or support for var keyword.

Though type inference was improved a lot in Java 8 with the introduction of the lambda expression, method reference, and Streams, local variables still needed to be declared with proper type but that's now gone. Java 10 has a feature, JEP 286: Local-Variable Type Inference which will allow declaring local variables without type information and by just using var keyword.

Java 10 var Examples

Here are some examples of Java 10 var keyword:

var str = "Java 10"; // infers String
var list = new ArrayList<String>(); // infers ArrayList<String>
var stream = list.stream(); // infers Stream<String>s

As I said, at this point you may not fully appreciate what var is doing for you but look at the next example:

var list = List.of(1, 2.0, "3")

Here list will be inferred into List<? extends Serializable & Comparable<..>> which is an intersection type.

The use of var reserve world also make your code concise by reducing duplication e.g. the name of the Class which comes in both right and left-hand side of assignments as shown in the following example:

ByteArrayOutputStream bos = new ByteArrayOutputStream();

Here ByteArrayOutputStream is repeating twice and we can eliminate that by using the var feature of Java 10 as shown below:

var bos = new ByteArrayOutputStream();

We can do similar things while using try-with-resource statements in Java e.g.

try (Stream<Book> data = dbconn.executeQuery(sql)) {
    return data.map(...)

can be written as follows:

try (var books = dbconn.executeQuery(query)) {
    return books.map(...)
These are just a few examples, there are a lot of places where you can use var to make your code more concise and readable, many of which you can see Sander's Pluarlsight course What's New in Java 10 course. It's a paid course but you can get it as free by signing up for 10-day free trial.

Finally, Java 10 has var to declare Local Variables - JDK 10 New Feature

Is Java Going Scala or Groovy Way?

For those programmers who have used Groovy or Scala, the introduction of var like Java going Scala way but that only time will tell. For now, we can just be happy that var makes it easier to declare a complex local variable in Java 10.

Anyway, the local variable type inference of simply Java 10 var keyword can only be used to declare local variables e.g. any variable inside method body or code block.

You cannot use var to declare member variables inside the class, method formal parameters or return type of methods.

For example, this example of var is OK:

public void aMethod(){
var name = "Java 10";

but the following is NOT OK

class aClass{
var list; // compile time error


So, even though this new Java 10 feature is eye-catching and looks good, it still has a long way to go, but you can start using it to further simplify your code. Less boilerplate code always means better and more readable code.

JEP 286: Local-Variable Type Inference - Things to remember

Now that you know that you can declare local variables without declaring the type in Java 10, it's time to learn few important things about this feature before you start using them in your production code:

1. This feature is built under JEP 286: Local-Variable Type Inference and authored by none other than Brian Goetz, author of Java Concurrency in Practice, one of the most popular books for Java developers and probably next to only Effective Java by Joshua Bloch.

2. The var keyword allows local variable type inference which means type for the local variable will be inferred by the compiler, you don't need to declare that.

3. The local variable type inference or Java 10 var keyword can only be used to declare local variables e.g. inside methods, on initializers code block, indexes in the enhanced for loop, lambda expression, and local variables declared in a traditional for loop.

You cannot use it for declaring formal variables and return types of methods, declaring member variables or fields, constructor formal variables and any other kind of variable declaration.

4. Despite the introduction of var, Java is still a statically typed language and there should be enough information to infer the type of local variable if not, the compiler will throw an error.

5. The var keyword of Java 10 is similar to the auto keyword of C++, var of C#, JavaScript, Scala, Kotlin, def of Groovy and Python (to some extent) , and : = operator of Go programming language.

6. One important thing to know is that, even though var looks like a keyword, it's not really a keyword. Instead, it is a reserved type name. This means that code that uses var as a variable, method, or package name will not be affected.

7. Another thing to note is that code that uses var as a class or interface name will be affected by this Java 10 change, but as JEP says, these names are rare in practice, since they violate usual naming conventions.

8. The immutable equivalent of local variables or final variables val and let is not yet supported in Java 10.

That's all about the var in Java 10, an interesting Java 10 features which allow you to declare local variables without declaring their type. This will also help Java developer to pick other languages quickly e.g. Python, Scala, or Kotlin because they heavily use var to declare mutable variables and val to declare immutable local variables. Even though JEP 286: Local-Variable Type Inference, only support var and not val, it still useful and feels like coding Scala in Java.

Further Learning
What's New in Java 10 by Sander Mak
Style Guidelines for Local Variable Type Inference in Java
JEP 286: Local-Variable Type Inference
Top 10 Java 8 Tutorials for Programmers
10 Things Java Developer Should learn in 2018
Top 10 Java 9 Tutorials for Programmers
The Complete Java MasterClass to learn Java Better

Thanks for reading this article so far. If you like this new Java 10 feature then please share with your friends and colleagues. If you have any questions or feedback, please drop a note and stay tuned for more Java 10 tutorials and articles here. 


Nandha Kumar said...

HI any one pls let me know, how can i filter based year and month

Javin Paul said...

Hello Nandha Kumar, you can access it on the right bottom corner of the blog. I had removed it earlier but added it back as a couple of my readers asked for it.

Unknown said...

Hi Javin,
Thank you for enabling the index (tree or filter) at the right bottom corner. I am not able to see all the blogs there from the start. They are only from 2016. As I remember and following you, the blogs were starting from around 2009-2010, correct? Please enable them all as they are very useful to traverse and study from beginning and till end.

--j aneiros said...

Hi Javin, thanks for the article. I think it would be interesting to note that by using var you'll be abandoning "programing for the interface":

The following will fail at compile time because the trimToSize method is not exposed.

List < String> statesList = new ArrayList<>(List.of("Florida", "Texas"));

The following will compile and run:

var varStatesList = new ArrayList<>(List.of("Florida", "Texas"));

Javin Paul said...

Hello janerios, good spot but isn't this code itself is not programming for interface because I am directly instantiating ArrayList, instead of calling a factory method like getList()? I believe in that case it will work as expected, no?

Post a Comment