At
Data Geekery, we love Java. And as we’re really into
jOOQ’s fluent API and query DSL, we’re absolutely thrilled about what Java 8 will bring to our ecosystem.
Java 8 Friday
Every Friday, we’re showing you a couple of nice new tutorial-style Java 8 features, which take advantage of lambda expressions, extension methods, and other great stuff.
You’ll find the source code on GitHub.
Language Design is Subtle
It’s been a busy week for us. We have just migrated the
jOOQ integration tests to Java 8 for two reasons:
- We want to be sure that client code compiles with Java 8
- We started to get bored of writing the same old loops over and over again
The trigger was a loop where we needed to transform a
SQLDialect[]
into another
SQLDialect[]
calling
.family()
on each array element. Consider:
Java 7
SQLDialect[] families =
new SQLDialect[dialects.length];
for (int i = 0; i < families.length; i++)
families[i] = dialects[i].family();
Java 8
SQLDialect[] families =
Stream.of(dialects)
.map(d -> d.family())
.toArray(SQLDialect[]::new);
OK, it turns out that the two solutions are equally verbose, even if the latter feels a bit more elegant. :-)
And this gets us straight into the next topic:
Backwards-compatibility
For backwards-compatibility reasons, arrays and the pre-existing Collections API have not been retrofitted to accommodate all the useful methods that Streams now have. In other words, an array doesn’t have a
map()
method, just as much as
List
doesn’t have such a method. Streams and Collections/arrays are orthogonal worlds. We can transform them into each other, but they don’t have a unified API.
This is fine in everyday work. We’ll
get used to the Streams API and we’ll love it, no doubt. But because of Java being extremely serious about backwards compatibility, we will have to think about one or two things more deeply.
Recently, we have published a post about
The Dark Side of Java 8. It was a bit of a rant, although a mild one in our opinion (
and it was about time to place some criticism, after all the praise we’ve been giving Java 8 in our series, before ;-) ). First off, that post triggered
a reaction by Edwin Dalorzo from our friends at Informatech. (Edwin has written this
awesome post comparing LINQ and Java 8 Streams, before). The criticism in our article evolved around three main aspects:
- Overloading getting more complicated (see also this compiler bug)
- Limited support for method modifiers on default methods
- Primitive type “API overloads” for streams and functional interfaces
A response by Brian Goetz
I then got a personal mail from no one less than
Brian Goetz himself (!), who pointed out a couple of things to me that I had not yet thought about in this way:
I still think you’re focusing on the wrong thing. Its not really the syntax you don’t like; its the model — you don’t want “default methods”, you want traits, and the syntax is merely a reminder that you didn’t get the feature you wanted. (But you’d be even more confused about “why can’t they be final” if we dropped the “default” keyword!) But that’s blaming the messenger (where here, the keyword is the messenger.)
Its fair to say “this isn’t the model I wanted”. There were many possible paths in the forest, and it may well be the road not taken was equally good or better.
This is also what Edwin had concluded. Default methods were a necessary means to tackle all the new API needed to make Java 8 useful. If
Iterator
,
Iterable
,
List
,
Collection
, and all the other pre-existing interfaces had to be adapted to accommodate lambdas and Streams API interaction, the expert group would have needed to break an incredible amount of API. Conversely, without adding these additional utility methods (
see the awesome new Map methods, for instance!), Java 8 would have been only half as good.
And that’s it.
Even if maybe, some more class building tools might have been useful, they were not in the center of focus for the expert group who already had a lot to do to get things right. The center of focus was to provide a means for API evolution. Or in Brian Goetz’s own words:
Reaching out to the community
It’s great that Brian Goetz reaches out to the community to help us get the right picture about Java 8. Instead of explaining rationales about expert group decisions in private messages, he then asked me to publicly re-ask my questions again on Stack Overflow (or lambda-dev), such that he can then publicly answer them. For increased publicity and greater community benefit, I chose Stack Overflow. Here are:
The amount of traction these two questions got in no time shows how important these things are to the community, so don’t miss reading through them!
“Uncool”? Maybe. But very stable!
Java may not have the “cool” aura that
node.js has. You may think about JavaScript-the-language whatever you want (as long as it contains swear words), but from a platform marketing perspective, Java is being challenged for the first time in a long time – and being “uncool” and backwards-compatible doesn’t help keeping developers interested.
But let’s think long-term, instead of going with trends. Having such a great professional platform like the Java language, the JVM, the JDK, JEE, and much more, is invaluable. Because at the end of the day, the “uncool” backwards-compatibility can also be awesome. As mentioned initially, we have upgraded our integration tests to Java 8. Not a single compilation error, not a single bug. Using
Eclipse’s BETA support for Java 8, I could easily transform anonymous classes into lambdas and write awesome things like these upcoming
jOOQ 3.4 nested transactions (API not final yet):
ctx.transaction(c1 -> {
DSL.using(c1)
.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME)
.values(3, "Doe")
.execute();
// Implicit savepoint here
try {
DSL.using(c1).transaction(c2 -> {
DSL.using(c2)
.update(AUTHOR)
.set(AUTHOR.FIRST_NAME, "John")
.where(AUTHOR.ID.eq(3))
.execute();
// Rollback to savepoint
throw new MyRuntimeException("No");
});
}
catch (MyRuntimeException ignore) {}
return 42;
});
So at the end of the day, Java is great. Java 8 is a tremendous improvement over previous versions, and with great people in the expert groups (and reaching out to the community on social media), I trust that Java 9 will be even better. In particular, I’m looking forward to learning about how these two projects evolve:
Although, again, I am really curious how they will pull these two improvements off from a backwards-compatibility perspective, and what caveats we’ll have to understand, afterwards. ;-)
Anyway, let’s hope the expert groups will continue to provide public feedback on Stack Overflow. Stay tuned for
more awesome Java 8 content on this blog.
Like this:
Like Loading...
Great article. The references to Brian Goetz answers are invaluable (the second link to SO did not work for me).
About your comment on Node.js, I have to say that I played a few hours with the early access of Project Avatar and I found that it is an interesting competitor to make Java more cool again :-) Instead of trying to stop the traction that JavaScript is gaining, Java embraces it, and with Nashorn all this possible.
Regarding the future of Java I am also really looking forward to see what are the plans for project Jgsaw and the Java modularization. Mark Reinhold had promise in his blog this would be part of the next release of Java. I built the JDK for Jigsaw like 6 months ago for the last time and it looks pretty advanced, so I really hope we don’t “miss the train this time”.
Thanks, fixed.
I haven’t had the chance to play around with Nashorn, yet. So far, I’ve only seen tutorialesque articles, but I’m looking forward to seeing something more serious. Also, if you ever decide to write up something on your early Jigsaw experience, that would be a very interesting read. Be sure to let me know!