Abstract: Local variable type inference is finally here, but dangers lurk. We might encourage overly long methods and lose the benefits of interface abstraction.
Welcome to the 255th edition of The Java(tm) Specialists' Newsletter. I know what you're thinking: This Heinz guy does not write to us for two months, and now three bulletins in three days? Is he lonely or something?
This will be short, I promise.
After a lunch of delicious pan-fried fresh European anchovies, I treated myself to a nap. I felt millennial-entitled, having crafted two newsletters in two days. When I awoke from my slumber, Jack Shirazi's newsletter was staring at me from my inbox. The title: "Java 10". Java 10? Really? Weren't we celebrating Java 9 a few months ago? Jack covered performance, so we will look at one of the language enhancements.
javaspecialists.teachable.com: Please visit our new self-study course catalog to see how you can upskill your Java knowledge.
The famous saying goes: Strong typing is for people with weak memories.
But Java is excessively pedantic.
int i = 42;
, when every school child knows that 42 is an int. It is also the meaning of everything,
but I digress. The first enhancement is with inferred local variables.
In Java 10, we do not need to explicitly declare the type of
local variables. We can write
var i = 42;
Consider this class from Java 9:
import java.util.*; public class Java9 { public static void main(String... args) { for (String arg : args) { System.out.println(arg); } for (int i = 0; i < args.length; i++) { String arg = args[i]; System.out.println(arg); } List<String> strings = new ArrayList<>(); strings.add("hello"); for (String string : strings) { } List<String> explicit = new ArrayList<>(); String name = "Hello"; name += " World"; System.out.println("name = " + name); int var = 42; // <-- hmmm, wonder what will happen? } }
In Java 10, we can leave out most of the explicit declarations and instead produce this:
import java.util.*; public class Java10 { public static void main(String... args) { for (var arg : args) { System.out.println(arg); } for (var i = 0; i < args.length; i++) { var arg = args[i]; System.out.println(arg); } var strings = new ArrayList<String>(); strings.add("hello"); for (String string : strings) { } List<String> explicit = new ArrayList<>(); var name = "Hello"; name += " World"; System.out.println("name = " + name); var var = 42; // <-- this works } }
We see that we can still use "var" as an identifier. This
tells me that var isn't a reserved word in Java. We cannot
write var assert = 2
. This is good news, as we
should still be able to compile code that uses var
for method, fields or variable names.
We can use the diamond operator for generics, but
then the type parameter defaults to Object. Thus
var strings = new ArrayList<>()
would infer the type as ArrayList<Object>
.
I foresee two dangers with this new language feature:
List
as a local variable type for
strings
. This reduces the methods available to
only those that List presents. For example, in the Java 9
version, we cannot call strings.trimToSize()
.
In Java 10, where we declared it as
var strings = new ArrayList<String>()
,
we lose the abstraction to List. Thus strings.trimToSize()
is available. This can get us into trouble when we
invoke methods from a particular implementation.
I am sure that I missed a lot of subtleties with this new language feature. Please write to me if you can think of nasty edge cases that we need to consider for future newsletters.
To try out Java 10, I downloaded the EAP version of IntelliJ IDEA 2018.1 and the JDK 10 Early Access Build.
Kind regards from Crete
Heinz
We are always happy to receive comments from our readers. Feel free to send me a comment via email or discuss the newsletter in our JavaSpecialists Slack Channel (Get an invite here)
We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.