Java 13 Text Blocks, Switch Update, Micronaut, Quarkus
CodeFX Occasionally #72 — 7th of June 2019
Hi everyone,
there’s been some new development on Java 13 and I recently experimented a little with the new, hot, and blazing fast web frameworks Quarkus and Micronaut, so I thought it’s time for another newsletter. Without further ado…
I send this newsletter out some Fridays. Or other days. Sometimes not for weeks. But as an actual email. So, subscribe!
Text blocks in Java 13
Good news, everyone, we got another shot at multiline strings, now called text blocks, in Java 13! Here you go:
String html = """
Hello, world
""";
Here are a few interesting details:
- the opening delimiter is not just
"""
, but includes the line terminator - yes there has to be a new line! - the closing delimiter can be on the last line or on its own line, depending on whether the string should end with a line terminator or not
- incidental white space is removed and there’s some complexity in identifying which white space is incidental and which isn’t — the position of the closing
"""
plays a critical role here - these blocks are not raw, i.e. escape sequences like
\t
and\n
are evaluated - best way to embed variables is something like
String::format
(there's neither interpolation nor are text blocks easy to concatenate) - this will be a regular
String
that, at run time, is indistinguishable from one created from a string literal
For more, read the JEP (or wait for the inevitable Twitch stream, blog post, YouTube video, etc. 😉).
Update: The inevitable stream happened and a post was published.
Micro-update to switch expressions in Java 13
The youngest Java language feature is the extension of switch
from statement to expression, which was introduced in Java 12 as a preview feature. Good thing about those previews is that it's far easier to experiment with them and gather experience that can be acted on before the change gets set into stone.
And this is exactly what happened here. The question was: How can a switch expression branch complete and denote its result:
boolean result = switch (ternaryBoolean) {
case TRUE -> {
System.out.println("Bool true");
// what do we replace "..." with?
... true;
}
// [...]
};
Maybe the most obvious, return
, doesn't work because it would cause confusion as to whether we're ending the switch expression or the entire surrounding method:
Digression: What’s so terrible about “return”, any why is it OK for lambdas but not OK for switches?
While we could of course define “return” to mean whatever we want, But, in imperative languages with the concept of “methods” or “procedures”, including Java, return has always had a clear meaning: unwind the current call frame, and yield the designated value to the caller. Lambda expressions are effectively method bodies (lambdas are literals for functional interfaces, which are single method interfaces), and so return (barely) fits. But switch expressions are most definitely not methods, and are not associated with call frames. Asking users to look at the enclosing context when they see a “return” in the middle of a method, to know whether it returns from the method or merely transfers control within the method, is a lot to ask. (Yes, I know lambdas ask this as well; this is why this was an uncomfortable choice, and having made this hole, I’m not anxious to expand it dramatically. If anything I’d prefer to close it, but that’s another bikeshed.).
(end digression)
[Brian Goetz]
In Java 12, the answer was break
, but not everybody liked it:
The overloading of break creates uncomfortable interactions. There is the obvious ambiguity between “break value” and “break label”; there is also the slightly less obvious interaction where we cannot permit “break value” inside a loop or statement switch inside an expression switch. While both of these can be “specified around”, they create distortions in the spec, which in turn creates complexity in the user model; these are a sign that we may be pushing something a bit too far. Further, historically “break” has been a straight transfer of control; this muddies up what “break” means.
[Brian Goetz]
Ok, so no break
. What then? For a while it seemed to be break-with
. Keyword management is a problem and hyphenated keywords may be a solution, but, hell, for now they look weird as fuck. But that's not the only concern:
We could surely take “break-with” and move on; it feels sufficiently “switchy”. But let’s look ahead a little bit. We’ve now confronted the same problem twice [with lambdas and switch]: an expression form that, in a minority use case, needed a way to express “stop computing this expression, because I’m done, and here’s its value.” (And, unfortunately, we have two different syntactic ways to express the same basic concept.) Let’s call these “structured expressions.”
We have two structured expression forms, and of the three numbers in computer science, “two” is not one of them. Which suggests we are going to face this problem again some day […] Let’s say for sake of argument that we might someway want to extend ternary expressions to support the same kind of “restricted block expressions” as expression switches. […]
String s = (foo != null) ? s : { println("null again at line" + __LINE__); break-with "null"; };
Such an expression needs a way to say “I’m done, here’s my value”, just as lambda and switch did before it. Clearly “return” is not the right thing here any more than it is for switches. And I don’t think “break-with” is all that great here either! It’s not terrible, but outside of a loop or switch, it starts to feel kind of forced. And it would be terrible to solve this problem twice with one-time solutions, and have no general story, and then have to come up with YET ANOTHER way of expressing the same basic concept. So regardless of what we expect for future expression forms, let’s examine what our options are that are not tied to call frames (return) or direct transfer of control (switches and loops.).
[Brian Goetz]
Long discussion ensues… with yield
as the result in Java 13:
boolean result = switch (ternaryBoolean) {
case TRUE -> {
System.out.println("Bool true");
yield true;
}
// [...]
};
With this change, switch expressions will remain in preview for another release and I expect it to become final in March 2020 with Java 14.
Micronaut and Quarkus
I recently played around with Micronaut and Quarkus and was impressed by how easy it is to get started. The Hello World Fallacy is a real thing, of course, so getting started fast doesn’t really mean a whole lot, but considering how young some of the involved tools are (particularly Graal), it’s still impressive.
In case you never heard about Micronaut and Quarkus, let me quickly introduce them. Both are frameworks for Java backends that promise fast startup and response times and low memory footprint. Both work well with Graal’s ahead of time compilation to a native image, which results in blazing fast startup times. Quarkus’ Hello World takes about 3 ms to launch on my five-year-old laptop. 3 fraking milliseconds! Amazing!
Here are a few differences I discovered in the two hours I spent with the frameworks:
- Micronaut supports more than just Java, namely also Groovy and Kotlin
[Update: I was wrong: Quarkus also supports Kotlin — thank Gunnar for pointing this out.] - Quarkus has the nicer site, but seems a little less refined than Micronaut
- both rely on specialized dependency injection frameworks because they need to avoid reflection at run time (reflection is bad for performance and doesn’t work well with Graal AOT)
- Quarkus’ Hello World compiled faster than Micronaut’s and launched an order of magnitude faster
- I saw no difference in response times between them
When starting to work on the site for my courses (yes, that’s still a thing), I went with Spring Boot. Now I’m considering to go with one of these two instead. Better performance is always nice, less memory footprint means lower cost, but most importantly, if I learn a technology that’s new to me, why not pick one that’s actually new. 😁
As it stands, I’d probably go with Micronaut because of its Kotlin support, but since I want to relaunch my online presence before continuing working on the courses, I have some time before I need to pick one of the two.
What I’ve been up to
As mentioned recently, I want to do a better job of letting you know about my various activities. Here’s my first shot at that — a new segment listing what I’ve done. I’d be thrilled to get your feedback on this, so let me know what you think, e.g. by mail to nipa@codefx.org.
CW20:
- 📄 Jakarta EE, javax, And A Week Of Turmoil
- 🎥 Caliz III: Hashing scripts and background compilation
- 🔴 TypeScript, Gatsby, and Hugo
CW21:
- 📣 To JAR Hell And Back at DevSum
- 📣 Lambdas And Streams For Aficionados at DevSum
CW22:
CW23:
- 📣 Best Practices Considered Harmful
- ✉️ (this one)
I want to do one thing per week, but I’m hoping for two. Worked out so far. 😁
Long shots
Here are three great reads, but they are a little longer:
- What is the most sophisticated piece of software/code ever written?
- the Origins of Opera and the Future of Programming
- Mercurial’s evolve extension and how to share mutable history with it