9. December 2020   Stefan Esterer

Current state of Java: #15 Edition

Now three months after the release of Java 15 (September 2020) and the release of Java 16 (March 2021), it is time to look at what Java 15 brought and what might be included in the Java 17 LTS Version (planned for September 2021).

But before we discuss this, we have to acknowledge the elephant in the room. Different polls (JRebel, JetBrains) indicate that the adoption of Java versions greater 8 is very slow (around 60% to 75% of developers are still using Java 8).  So the new Java release schedule does not seem to have led to a wider adoption of non LTS java versions. Additionally library and framework developer are not very happy with the new system (as this talk from ApacheCon 2019 shows).

Does this mean, that we should ignore Java versions greater than 8 and focus on the next LTS version when we have to? I would argue for something different. 

There are applications which have no tolerance for any kind of risk. You don’t want to introduce a new Java version every 6 months (because it is optimized for Java 8, there are incompatible libraries, testing takes much time and so on). But just staying on Java 8 will be a problem in the future. And then you have to migrate a big complicated application with no or little experience with the new Java versions.

I would suggest to have some applications which are switching every 6 month to the new Java non LTS versions. This way you have the benefit of the underlying performance enhancements and also experience problems with the new versions in smaller and more manageable bits. That way you get a sense of what you need to do when and if you have to migrate the bigger and more complicated / business critical applications.

So with this stuff out of the way, what is shiny and new in Java 15?

Text Blocks (JEP-378)

Text Blocks (JEP 378) are out of preview, so they will be included in the next LTS Java version 17. What are they about? I’m sure you know code looking like this:

String html = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";
view raw oldstyle.java hosted with ❤ by GitHub

But with the new Java feature you can write this cumbersome code much more easily.

String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
view raw textblocks.java hosted with ❤ by GitHub

For more details how that works and what options there are, just have a look at JEP 378 (which I recommend you to anyway, it’s interesting to read about the motivations and the design choices).

Preview Feature: Records (JEP-384)

The title already tells you: This is a feature which is included in Java 15, but only as an preview feature. This means two things: First you have to activate this feature in your favorite IDE, in your build tool or directly on the command line (for more information look at the docs at oracle). 

The intent and content of this feature (JEP-384) is best summarized like that

Enhance the Java programming language with records, which are classes that act as transparent carriers for immutable data. Records can be thought of as nominal tuples.

I’m sure I’m not the only one creating tons of data objects with getter/setter/equals/hashCode() methods which are a hassle to write and a lot of boilerplate to read. With records, such a data object looks like that:

record Point(int x, int y) { }
view raw record.java hosted with ❤ by GitHub

This record has two fields (x,y) implicitly. It has a nice toEquals and hashCode method. You can even add other methods to this record if you want.

What I’m really looking forward is using the feature called local records. This can make stream operations much more readable by having a way to define named tuples which you can use in a method scope.

List<Merchant> findTopMerchants(List<Merchant> merchants, int month) {
// Local record
record MerchantSales(Merchant merchant, double sales) {}
return merchants.stream()
.map(merchant -> new MerchantSales(merchant, computeSales(merchant, month)))
.sorted((m1, m2) -> Double.compare(m2.sales(), m1.sales()))
.map(MerchantSales::merchant)
.collect(toList());
}
view raw localRecord.java hosted with ❤ by GitHub

So you might ask: Are records part of Java 17? Right now there is no answer to that. We’ll have to wait and see if the feature goes out of preview with Java 16 or even only with the LTS version 17.

Wrapping up…

There are more changes and preview features in Java 15 (e.g. sealed classes – JEP-360). The goal of this blog post was to show, that even if you don’t need the latest and greatest feature of the non LTS versions of Java it makes sense that you have a more detailed look at them and even use them in you daily work and production.