Cool Tools and Other Stuff JavaOne 2010: Upcoming Java Features by Eric Armstrong September 23, 2010
Summary
An overview of upcoming features in Java.
Advertisement
In the Java booth, Jim Holmlund gave me an overview of upcoming
features in Java. (Luckily for me, he had a copy of the speaker's
slides. So it made up for the session I missed in the morning.)
Some of what's coming is pretty cool. Some is a bit dissapointing,
compared to what I was hoping for. Here's my notes:
Java 7
Java 7 will get a variety of small language enhancements that are
part of the COIN
project:
Strings in Switch Statements A long overdue addition, the switch statement will find uses outside of low-level tokenizers that switch
on character bytes and integers. It will be possible to compare
strings, making a "dispatch" utility that will have many uses.
Underscores in constants When you're putting 1000000 miliseconds into a constant, you'll
be able to make it more readable by writing
it as 1_000_000. The compiler will then strip out the underscores
to produce the actual constant.
Multi-catch Instead of being limited to a single exception per catch clause, you'll be able to catch multiple exceptions
in one clause, and handle them each in the same way.
Autoclose interface One of Ruby's goodnesses here. If you implement the autoclose
interface, you can put input and output streams in a single try block
and, when the block ends, all of the streams are closed. It's an important
feature that saves you the headache of making sure that you close everything
when an exception disrupts the flow of processing. It will also eliminate
memory leaks that can accumulate when programs are terminated abnormally,
either externally or internally. That capability, in turn, means that
a VM will be able to stay up longer before memory leaks force it to its
knees.
Default methods for interfaces
When defining an interface, it will be possible to specify a default implementation
for a method signature. That feature helps in two ways. First, it means that
implementation code which is typically written the same way can be provided
in one DRY location. Second, it means that an interface designer can provide
null implementations for features to be added at a later date. The idea is
that older code won't break when new features are added to implementation
objects.
For example, let's say you publish a tree-processing interface.
Any object that implements that interface can be given to your summation
method, which will add up all the values in that tree. (A directory tree,
for example, with a count of files in each directory.) I use that summation
processor, and you do too. One day, you know you'll want to add up the file
sizes, as well. But you don't have time to implement
it right now. If you require tree interface to have a size() method, you
force me to implement it, even though it's never used. But if you don't,
you can't add it later without breaking my implementation. You naturally
don't want to do that, so you define a default size() method. Then, when
you get around to it, you define a diskSpace() method that takes a Tree
object, and you define a size() method in your DirectoryTree implementation.
Everything works for you. As for me, I never implement size(), but
I don't care: I never use that newfangled diskSpace() method
anyway, so the default implementation of t size() is good enough
for me.
Type "Inferencing"
This is one that sounded good on paper, until I found it what it actually meant.
I was hoping for something that
would put an end to "viral generics". You know, when a library
returns a generic, and you call that API, now you have to put the
generics on your variable to make the warning go away--and when you return
it, everything that calls you has to have generics added. (Old languages
used to have 4 pages of warnings, making it hard to spot the errors.
To this day, I dislike warnings.)
So my expectation for "type inferencing" was that it would work sort
of like Ruby or Scala. If f(x) returns an ArrayList of String,
then there would be no need to code ArrayList<String> list = f(x).
Instead, you would just code
list = f(x), like you used to, and the compiler would
figure it out..
No such luck. Instead of inferencing from right to left, as
I expected, it works the other way around.
Instead of specifying
this: List<List<String>> list = new ArrayList<List<String>>();
You'll be able to specify this: List<List<String>> list =
new ArrayList<>();
Granted, it's an improvement. But it's a pretty small improvement. And it's
not even really type inferencing. Instead, it's type deduction: If
you tell the compiler what the type is on the left side of the
assignment, it can figure out what the type has to be on the right side, a few
characters later. I should hope so.
Pardon my disappointment, but I was looking for a lot more.
Java 8(ish)
VM Support for Dynamic Languages:
These features will make it
possible for truly dynamic languages to be implemented without
compromise. (Fully dynamic type safety for languages like JRuby
comes to mind as one of the features that will probably be implemented.)
LambdaJ:
This features makes functions into first-class objects
so that, for example, an anonymous function can be passed as an argument
to a method, using syntax like this:
#{..function definition here...}
That's an important step towards functional programming
capabilities, of course. But it's only one of several steps that
are needed, and it's going to be a year or two before Java 8 is available.
(For more on that subject, see the next report.)
Eric Armstrong has been programming and writing professionally since
before there were personal computers. His production experience includes artificial intelligence (AI) programs, system libraries, real-time
programs, and business applications in a variety of languages. He works as a writer and software consultant in
the San Francisco Bay Area. He wrote The JBuilder2 Bible and authored the Java/XML programming tutorial available at http://java.sun.com. Eric is also involved in efforts to design knowledge-based collaboration systems.