What happened to Java after 8? Java 15 and the Future

Okan Menevşeoğlu
Blue Harvest Tech Blog
13 min readOct 14, 2020

Hi everyone,

If you are a Java developer who got lost in the Java release train, don’t panic! Most of the Java developers couldn’t follow it properly after version 8. In this writing, I will explain why Java started to change so fast, which version brought which essential changes, and how to stay in the loop.

Long Time Support (LTS)

Old Java developers know that Oracle was releasing a new major Java version every 3 to 4 years. To adapt to the swiftly changing software world, they decided to move into a more agile way by releasing a new version every six months. They also started to collect feedback related to some new features by publishing them as previews. The first agile version was Java 9, which got released in September 2017. Six months later, Java 10 emerged as a new requirement for some recruiters, and then Java 11 followed it with a similar release interval.

With Java 11, Oracle said that this version would have Long Time Support (LTS). It means Oracle will provide support and updates until 2026. That brought some relief to the market. On the other hand, Oracle will continue supporting Java 8 until 2030 because of its vast market share. When you think about some legacy codes that still use Java 7 and less, I believe it is a well-made choice to support Java 8 for longer.

Java Release Train from Wikipedia

By the time of this writing, Java 15 has just released to the market with more features. However, we can see on the table that Java 17 is scheduled for September 2021 to be the next LTS version. This actually puts 3 years between the last two LTS versions which actually gives enough time for developers to explore and migrate.

Jakarta EE is the New Java EE

Java EE (Enterprise Edition) is also still supported under a new name called Jakarta EE by Eclipse Foundation. For those who don’t know the details of Java EE, it is a platform that provides an API and a runtime environment for building and running large-scale, multi-tiered, scalable, reliable, and secure network applications as explained by Oracle.

If you have any experience with a framework such as Spring MVC/Spring Boot, then Jakarta EE specifications may sound familiar. The main difference is, Jakarta EE is mainly high-level specifications, and their implementations vary. For example, GlassFish, JBoss, and WebSphere are different Jakarta EE based application server implementations. That is also one of the reasons that companies keep their distance to Jakarta EE.

Major Changes in Each Version

Each Java version brings some significant changes and some minor changes to the language. The list can be quite long, but there are some features that I believe every Java developer should know. Below, you can find which version brought which major change, so you can decide if you want to adopt them or not.

Java 9

Java 9 is released in September 2017, and even though there were several changes, 3 of them are the most important. For the complete list of changes, you can refer here.

1. Modularity

The most significant change in Java 9 was the modularity system that was named as Jigsaw Project.

A module is a group of code that has common features. As its name indicates, modularity divides Java into modules to provide shadowing, reduce version conflicts, add more encapsulation, more security, more performance, and customized runtime JDKs with smaller size.

To create a new module, you need a module-info.java file under your src.main.java directory. Inside, you can define your module requirements.

An example of module creation.

The example shows that the module should be limited to use only the above packages besides the java.base. After you create it, you can export it in another module to be able to use it. I would advise creating a dummy project with 2–3 modules and experimenting to understand it better.

2. Private methods in Interfaces

The next Java 9 feature enables writing private and private static methods in interfaces to avoid redundant code.

To demonstrate this, I will create an example of a real-world case and use “money transfer”. First, we need to create our interface and service class.

Money Transfer Interface

This is a simple example. As you can see above, there is a private method in the interface private void errorImplementation(String name). It is called by the default interface methods with different error names.

Money Transfer Service

If an implementation for a default interface method is omitted, it throws an exception. The private method encapsulates the exceptions inside the interface.

Money Transfer Test

We execute our test, and the results are as the following:

Money Transfer Test Result

When you call the transfer() method, which has an implementation, you see that it ran successfully. However, when it tries to execute the viewMoneyTransfer() method, it throws an exception from the private interface method.

3. New REPL Feature (JShell)

Oracle developed a new REPL tool called JShell. REPL stands for Read-Evaluate-Print-Loop. As its name describes, it is used to help developers run commands, create variables, classes, methods, and test them quickly.

You can start it by typing jshell on the command line and begin writing code instantly.

JShell in action

As you can see above, you can create a method and call it without assigning it to a variable, and you don’t need to use semicolons either. Moreover, you can override variables by setting new types to them. It is perfect for exploratory programming.

Java 10

Java 10 is released six months later than Java 9 in March 2018 and brought two significant changes. You can find the rest of the changes here.

1. Oracle JDK vs. Open JDK

To be more developer-friendly, Oracle & Java community started to promote the OpenJDK binaries as the primary JDK going forward. However, if you want to get an actual Oracle JDK and extended support for older LTS versions such as 8 and 11, you need to subscribe to Oracle.

2. Local-Variable Type Inference

Java 10 brought the var keyword, which exists in many other languages for implicit typing. Implicit typing means that you can assign any type of object to it. However, in Java, you can’t change the variable type after you define it. This makes Java to still be a static language.

Several use cases for the var keyword

The main benefit of using the var keyword is to reduce the verbosity of the language. You can avoid long object names or writing the same return types/class names twice.

At first sight, you can ask the following question: “What is the difference between var and Object then?”. The answer is; var keyword means that you want the compiler to figure the type out.

Using the Object type with a custom class is not possible.

Using the Object keyword upcasts your object to the Object type. This means that even though you can use the generic Object class methods, you can’t use your class-specific methods. It will create a compile-time error.

Java 11

Java 11, as part of the new release train cycle, is released six months later than Java 10 in September 2018. It brought two critical changes and is also the latest LTS version until Java 17. You can read the full list of changes from here.

1. No more javac

Starting from Java 11, you don’t need to use javac anymore to compile your java files. Instead, you can just run java, and it will compile and run the files!

2. Local-Variable Syntax for Lambda Parameters

The only language change in Java 11 was the support for the new var keyword as Lambda parameters.

An example of usage.

The benefit of this usage comes to the scene, especially when you want to do an annotation validation.

Java 12

Java 12 is released in March 2019 and brought one significant improvement on the switch keyword as a preview. The full change list is available here.

1. Switch to “switch Expressions” (Preview)

Java developers usually hate the switch statements because of their ugly syntax and dangerous fallbacks. Java 12 has brought preview for a cleaner way to write statements with new switch expressions.

Switch statements before Java 12.

Before Java 12, switch statements could cause ugly code blocks. This has changed with the new arrow style statements and switch expressions.

Java 12 switch expressions

As you can see above, you can assign the result to a new variable for later use, and the code looks much cleaner and shorter.

Java 13

Java 13 is released in September 2019 and brought two major preview improvements. You can refer here for the complete list of changes.

1. Text Blocks (Preview)

The new text blocks preview feature enabled developers to be able to read multi-line texts easier. It uses three quotes, similar to Python and Groovy:

Text blocks make the text more readable.

2. Switch Expressions Enhancements: yield (Preview)

Switch expressions previews are also improved, and now you can directly return a value with the yield keyword. It was also possible before such asbreak "Monday"; , but to reduce confusion and improve readability, the break with value option is dropped. (Please note that break keyword is still there for statements.) To distinguish a statement and an expression better, the yield keyword is introduced as an alternative to arrow syntax.

Java 13 yield keyword

Java 14

Java 14 is released in March 2020 and brought five major improvements. You can refer here for the complete list of changes.

1. Switch Expressions as a standard

Switch expressions that were introduced as a preview in Java 12 and got improved in 13 have become a language standard.

2. NullPointerExceptions Enhancement

NullPointerExceptions can be quite hard to track down. Java 14 is taking a step and making them more meaningful. Let’s give an example;

An example call.
NPE before Java 14.

If we ran the first code block before Java 14, we could get the above error, not giving details about what is wrong except the class name and the line number. The message is greatly improved in 14;

NPE in Java 14.

Besides the class name and line number, we can also see which parameters or method invocation causes the NPE. This is very helpful for debugging.

3. Records (Preview)

One of the preview features of JDK 14 is records. It is implemented to reduce the verbosity of the language. It is better to explain it in an example;

A final Person class.

As you can see above, we have a simple Person method that contains private final fields, all args constructor, getters, equals, toString, and hashCode. The above code contains 37 lines. With the new record keyword, the above is reduced to a single line;

The new Person record.

It is exactly the same as the first code block. Moreover, you can customize the constructor initialization;

You can add conditional checks.

You can experiment with this by enabling the preview features of JDK 14.

4. Pattern Matching for instanceof (Preview)

Another preview is on the instanceof keyword. We can now give a variable name during the conditional checks. It is enhanced to reduce additional castings. To give an example;

Old pattern matching.

It has changed from above to;

The new pattern matching.

As you can see, there are two changes. First is that we don’t need to cast the obj to String, and the second is that the if condition also covers instanceof keyword itself. The first code block doesn’t throw an error if obj is null. To do that, we need another else in the first block, which will make it even more verbose. On the other hand, the second one also covers the null case and throws an exception if obj is null.

5. Z Garbage Collector (ZGC) (Experimental)

Finally, the old garbage collector got an experimental update with Java 14. As picked up from OpenJDK Wiki:

At its core, ZGC is a concurrent garbage collector, meaning all heavy lifting work is done while Java threads continue to execute. This greatly limits the impact garbage collection will have on your application’s response time.

It reduces the Garbage Collector's performance impact on your application by running it concurrently. This is introduced as an experimental feature and can be used by adding the following JVM flags;-XX:+UnlockExperimentalVMOptions and -XX:+UseZGC on both Windows and macOS.

Java 15

Java 15 has recently released on 15 September 2020 and brought four major improvements. You can refer them here for the complete list of changes.

1. Text Blocks as Standard

Text blocks that are introduced as a preview in Java 13 have become a language standard.

2. Sealed Classes (Preview)

Sealed classes are an enchantment to Object-Oriented Programming in Java. sealed and non-sealed are two keywords that are introduced as a preview in Java 15.

The sealed keyword creates a contract with a class or an interface to specify which subclasses can extend or implement them.

non-sealed keyword, in short, breaks this contract and allows subclasses to continue to extend them.

I believe it is much easier to explain with an example. Let’s assume we have an interface called Drivable, which is a sealed interface that permits only Vehicle class.

A sealed Drivable interface

The Drivable interface has one method called accelerate(). Let’s assume that Vehicle class is an abstract but also non-sealed ;

A non-sealed Vehicle class that implements a Drivable interface as it is permitted.

This means that the contract is broken, and any class can extend the Vehicle. If we didn’t want to break the contract, we should have defined the Vehicle class as final or also sealed.

A Car class that extends the non-sealed Vehicle abstract class.

As you can see, now another class, Car, can extend Vehicle freely.

A Horse class that tries to implement Drivable, but it is not permitted.

However, Horse class, which tries to implement the Drivable interface, is not able to because it is not permitted by the sealed Drivable interface.

Here is also a diagram to understand it better:

Java 15 Sealed Classes Example Hierarchy

3. Edwards-Curve Digital Signature Algorithm (EdDSA)

Java 15 also comes with a feature to create a key pair and sign it using modern cryptographic EdDSA. Some libraries are already providing this feature, but now it is a core feature of Java itself.

4. Hidden Classes

Finally, Java 15 comes with a feature called hidden classes. To give a brief explanation, these classes are meant to be used by framework creators at the bytecode level via reflection to prevent non-framework related usage by other classes. However, this is an advanced topic which I believe is out of scope for a standard developer. For more information, you can refer to JDK docs.

Java 16 & Future

Java 16 and onwards will continue to be released every six months. Java 16 will arrive in March 2021, and Java 17, which will be the next LTS version, will be released on September 2021. According to the plan, in version 17, all experimental and preview features between JDK 11 and JDK 17 will become standards.

So, why does the Java world is stuck to version 8?

There is more than a single answer to this. The first reason is that most of the features are currently in preview. The versions between LTS versions are for both improving the language and previewing some features. Thus, making it a bit experimental rather than production-ready.

The second reason is that, for small companies, it is easier to update versions. However, for large corporations, it takes many security and compliance approvals to increase a version. When you also consider integrations that might fail with a single version, it can take months to do the migration process.

The third and final reason is the frameworks and libraries. Frameworks such as Spring and libraries like Lombok, etc. are often used, especially by Web developers, and they mostly solve broader problems. For example, I might still use Lombok instead of records. Even though it is relatively more verbose, Lombok gives more flexibility over different types of classes possible to implement.

Shall I upgrade to Java 15?

Unless you are interested in using one of the new features; you should stick to Java 11 or upgrade to it if you using a lower version. You can follow up on the changes and experiment with them until next September when Java 17 releases and upgrade when it is here. Of course, increasing versions one at a time can also be beneficial for avoiding unexpected errors, especially if you have a complex architecture. Upgrading six versions at once is usually tend to bring more problems. However, it is up to you to upgrade beyond Java 11.

Conclusion

It was a bold move for Oracle to move to an agile approach, but I believe it was the correct move. They can gather more feedback on the features, and we can experiment on them before the LTS version is here. This gives developers fewer surprises by knowing what is coming beforehand and preventing getting overwhelmed by the features.

Annoucment: We are hiring! If you are interested in similar technologies and would like to work with us, check our careers page. We are looking for enthusiastic candidates, especially for Belgium. So, send us your CV!

That being said, feel free to experiment as much as you want with Java 15, and see you when Java 16 is released!

--

--