What is var in Java
var predefined type introduced in Java 10 lets you declared local variables without specifying the type of the variable when you assign a value to the variable. When you assign a value to a variable the type of the expression already defines the type of the variable, thus there is no reason to type the type on the left side of the line again. It is especially good when you have some complex long types with a lot of generics, for example
Generic types you could already inherit in prior Java versions but now you can simply type
This is simpler, and most of the times more readable than the previous version. The aim of the
var is mainly readability. It is important to understand that the variables declared this way will have a type and the introduction of this new predefined type (not a keyword) does not render Java to be a dynamic language. There are a few things that you can do this way that you could not before or you could do it only in a much more verbose way. For example, when you assign an instance of an anonymous class to a variable you can invoke the declared methods in the class through the
var declared variables. For example:
you can invoke the method
z() but the code
does not compile. You can do that because anonymous classes actually have a name at their birth, they just lose it when the instance gets assigned to a variable declared to be the type of
There is a little shady part of the
var keyword. This way we violate the general rule to instantiate the concrete class but declare the variable to be the interface. This is a general abstraction rule that we usually follow in Java most of the times. When I create a method that returns a
HashMap I usually declare the return value to be a
Map. That is because
HashMap is the implementation of the return value and as such is none of the business of the caller. What I declare in the return type is that I return something that implements the
Map interface. The way I do it is my own duty. Similarly, we declare usually the fields in the classes to be of some interface type if possible. The same rule should also be followed by local variables. A few times it helped me a lot when I declared a local variable to be
Set but the actual value was
TreeSet and then typing the code I faced some error. Then I realized that I was using some of the features that are not
SortedSet. It helped me to realize that sorted-ness is important in the special case and that it will also be important for the caller and thus I had to change the return type of the method also to be
SortedSet. Note that
SortedSet in this example is still an interface and not the implementation class.
With the use of
var we lose that and we gain a somewhat simpler source code. It is a trade-off as always. In case of the local variables the use of the variable is close in terms of source code lines to the declaration, therefore the developer can see in a glimpse what is what and what is happening, therefore the “bad” side of this tradeoff is acceptable. The same tradeoff in case of method return values or fields is not acceptable. The use of these class members can be in different classes, different modules. It is not only difficult but it may also be impossible to see all the uses of these values, therefore here we remain in the good old way: declare the type.
The future of var (just ideas)
There are cases when you cannot use
var even for local variables. Many times we have the following coding pattern:
Here we can not use
var because there is no expression assigned to the variable on the declaration itself. The compiler, however, could be extended. From now on what I talk about is not Java as it is now. It is what I imagine how it can be in some future version.
If the structure is simple and the “do something here” is empty, then the structure can be transformed into a ternary operator:
In this case, we can use the
var declaration even if we use an old version of Java, e.g.: Java 11. However, be careful!
What will be the actual type of the variable
h in this example?
Number? The ternary operator has complex and special type coercion rules, which usually do not cause any issue because the two expressions are close to each other. If we let the structure described above use a similar type coercion then the expressions are not that close to each other. As for now, the distance is far enough for Java not to allow the use of the
var type definition. My personal opinion is that the
var declaration should be extended sometime in the future to allow the above structure but only in the case when the two (or more in case of more complex structure) expressions have exactly the same type. Otherwise, we may end up having an expression that results in an
int, another that results in a
String and then what will the type of the variable be? Do not peek at the picture before answering!
(This great example was given by Nicolai Parlog.)
I can also imagine that in the future we will have something that is similar to Scala
val, which is
final var in Java 11. I do not like the
val naming though. It is extremely sexy and geekish, but very easy to mistake one for the other. However, if we have a local variable declaration that starts with the
final keyword then why do we need the
var keyword after that?
Finally, I truly believe that
var is a great tool in Java 11, but I also expect that it’s role will be extended in the future.
Opinions expressed by Java Code Geeks contributors are their own.