JAVA Versions

Rashmi Nagarahalli
9 min readSep 15, 2023

--

What is the latest Java version?
As of September 2023, Java 21 is the latest released Java version. The current long-term support version (LTS) of Java is Java 21, released in September 2023.

Road map of Java versions:

Java Versions which are still maintained: Java SE 8, Java SE 11, Java SE 17, Java SE 21.

Java Latest Version: Java SE 22

Java Future release versions: Java SE23.

Why are companies still stuck with Java 8?
There’s a mix of different reasons some companies are still stuck with Java 8. To name a few:

Build tools (Maven, Gradle etc.) and some libraries initially had bugs with versions Java versions > 8 and needed updates. For example, certain build tools like Maven would print out “reflective access”-warnings when building Java projects, which simply “felt not ready”, even though the builds were fine.

Up until Java 8 you were pretty much using Oracle’s JDK builds and you did not have to care about licensing. Oracle changed the licensing scheme In 2019, though, which led the internet go crazy with a ton of articles saying “Java is not free anymore” — and a fair amount of confusion followed. This is however not really an issue, which you’ll learn about in the Java Distributions section of this guide.

Some companies have policies to only use LTS versions and rely on their OS vendors to provide them these builds, which takes time.

To sum up: you have a mix of practical issues (upgrading your tools, libraries, frameworks) and political issues.

Why are some Java versions, like 8 also called 1.8?
Java versions before 9 simply had a different naming scheme. So, Java 8 can also be called 1.8, Java 5 can be called 1.5 etc. When you issued the ‘java -version’ command, with these versions you got output like this:

Which simply means Java 8. With the switch to time-based releases with Java 9 the naming scheme also changed, and Java versions aren’t prefixed with 1.x anymore. Now the version number looks like this:

OPEN JDK BUILDS:

What is the difference between the Java versions? Should I learn a specific one?
Coming from other programming languages with major breakages between releases, like say Python 2 to 3, you might be wondering if the same applies to Java.

Java is special in this regard, as it is extremely backwards compatible. This means that your Java 5 or 8 program is guaranteed to run with a Java 8–20 virtual machine — with a few exceptions you don’t need to worry about for now.

It obviously does not work the other way around, say your program relies on Java 20 features, that are simply not available under a Java 8 JVM.

This means a couple of things:

  1. You do not just “learn” a specific Java version, like 12.
  2. Rather, you’ll get a good foundation in all language features up until Java 8. This serves as a good base.
  3. And then learn, from a guide like this, what additional features came in Java 9–20 and use them whenever you can.

Java Features from Version 8 to Version 21:

Java 8
Lambda Expressions and Stream API
Method Reference
Default Methods
Type Annotations
Repeating Annotations

Java 9
Java Module System
Try-with-resources
Diamond Syntax with Inner Anonymous Classes
Private Interface Methods

Java 10
Local Variable Type Inference

Java 11
Local Variable Type in Lambda Expressions

Java 14
Switch Expressions

Java 15
Text Blocks

Java 16
Pattern Matching of instanceof
Records

Java 17
Sealed Classes

The main changes of the Java 8 release are:

Java 8 was a massive release and you can find a list of all features at the Oracle website. There’s two main feature sets I’d like to mention here..

Language Features: Lambdas etc.
Before Java 8, whenever you wanted to instantiate, for example, a new Runnable, you had to write an anonymous inner class like so:

Runnable runnable = new Runnable(){
@Override
public void run(){
System.out.println("Hello world !");
}
};

With lambdas, the same code looks like this:

Runnable runnable = () -> System.out.println("Hello world two!");

Collections & Streams
In Java 8 you also got functional-style operations for collections, also known as the Stream API. A quick example:

List<String> list = Arrays.asList("franz", "ferdinand", "fiel", "vom", "pferd");

Now pre-Java 8 you basically had to write for-loops to do something with that list.

With the Streams API, you can do the following:

list.stream()
.filter(name -> name.startsWith("f"))
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println);

The main changes of the Java 9 release are:

Collections
Collections got a couple of new helper methods, to easily construct Lists, Sets and Maps.

List<String> list = List.of("one", "two", "three");
Set<String> set = Set.of("one", "two", "three");
Map<String, String> map = Map.of("foo", "one", "bar", "two");

Streams
Streams got a couple of additions, in the form of takeWhile,dropWhile,iterate methods.

Stream<String> stream = Stream.iterate("", s -> s + "s")
.takeWhile(s -> s.length() < 10);

Optionals

Optionals got the sorely missed ifPresentOrElse method.

user.ifPresentOrElse(this::displayAccount, this::displayLogin);

Interfaces

Interfaces got private methods:

public interface MyInterface {

private static void myPrivateMethod(){
System.out.println("Yay, I am private!");
}
}

The main changes of the Java 10 release are:

Local-Variable Type Inference: var-keyword

// Pre-Java 10

String myName = "Marco";

// With Java 10

var myName = "Marco"

The main changes of the Java 11 release are:

Strings & Files
Strings and Files got a couple new methods (not all listed here):

"Marco".isBlank();
"Mar\nco".lines();
"Marco ".strip();

Path path = Files.writeString(Files.createTempFile("helloworld", ".txt"), "Hi, my name is!");
String s = Files.readString(path);

Run Source Files
Starting with Java 10, you can run Java source files without having to compile them first. A step towards scripting.

~$ java MyScript.java

Local-Variable Type Inference (var) for lambda parameters
The header says it all:

(var firstName, var lastName) -> firstName + lastName

The main changes of the Java 12 release are:

Java 12 got a couple new features and clean-ups, but the only ones worth mentioning here are Unicode 11 support and a preview of the new switch expression, which you will see covered in the next section.

The main changes of the Java 13 release are:

You can find a complete feature list here, but essentially you are getting Unicode 12.1 support, as well as two new or improved preview features (subject to change in the future):

Switch Expression (Preview)
Switch expressions can now return a value. And you can use a lambda-style syntax for your expressions, without the fall-through/break issues:

Old switch statements looked like this:

switch(status) {
case SUBSCRIBER:
// code block
break;
case FREE_TRIAL:
// code block
break;
default:
// code block
}

Whereas with Java 13, switch statements can look like this:

boolean result = switch (status) {
case SUBSCRIBER -> true;
case FREE_TRIAL -> false;
default -> throw new IllegalArgumentException("something is murky!");
};

Multiline Strings (Preview)
You can finally do this in Java:

String htmlBeforeJava13 = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";

String htmlWithJava13 = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";

The main changes of the Java 14 release are:

Switch Expression (Standard)
The switch expressions that were preview in versions 12 and 13, are now standardized.

int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
default -> {
String s = day.toString();
int result = s.length();
yield result;
}
};

Records (Preview)
There are now record classes, which help alleviate the pain of writing a lot of boilerplate with Java.

Have a look at this pre Java 14 class, which only contains data, (potentially) getters/setters, equals/hashcode, toString.

final class Point {
public final int x;
public final int y;

public Point(int x, int y) {
this.x = x;
this.y = y;
}
}

With records, it can now be written like this: Again, this is a preview feature and subject to change in future releases.

record Point(int x, int y) { }

Garbage Collectors
The Concurrent Mark Sweep (CMS) Garbage Collector has been removed, and the experimental Z Garbage Collector has been added.

The main changes of the Java 15 release are:

Text-Blocks / Multiline Strings
Introduced as an experimental feature in Java 13 (see above), multiline strings are now production-ready.

String text = """
Lorem ipsum dolor sit amet, consectetur adipiscing \
elit, sed do eiusmod tempor incididunt ut labore \
et dolore magna aliqua.\
""";

Sealed Classes — Preview
If you ever wanted to have an even closer grip on who is allowed to subclass your classes, there’s now the sealed feature.

public abstract sealed class Shape
permits Circle, Rectangle, Square {...}

This means that while the class is public, the only classes allowed to subclass Shape are Circle, Rectangle and Square.

Records & Pattern Matching
The Records and Pattern Matching features from Java 14 (see above), are still in preview and not yet finalized.

Nashorn JavaScript Engine
After having been deprecated in Java 11, the Nashorn Javascript Engine was now finally removed in JDK 15.

ZGC: Production Ready
The Z Garbage Collector is not marked experimental anymore. It’s now production-ready.

The main changes of the Java 16 release are:

Pattern Matching for instanceof
Instead of:

if (obj instanceof String) {
String s = (String) obj;
// e.g. s.substring(1)
}

//You can now do this:
if (obj instanceof String s) {
// Let pattern matching do the work!
// ... s.substring(1)
}

Foreign Linker API — Preview
A planned replacement for JNI (Java Native Interface), allowing you to bind to native libraries (think C).

Records & Pattern Matching
Both features are now production-ready, and not marked in preview anymore.

Sealed Classes
Sealed Classes (from Java 15, see above) are still in preview.

The main changes of the Java 17 release are:

Java 17 is the new long-term support (LTS) release of Java, after Java 11.

Pattern Matching for switch (Preview)
Already available in many other languages:

public String test(Object obj) {

return switch(obj) {

case Integer i -> "An integer";

case String s -> "A string";

case Cat c -> "A Cat";

default -> "I don't know what it is";

};

}

Now you can pass Objects to switch functions and check for a particular type.

Sealed Classes (Finalized)
A feature that was delivered in Java 15 as a preview is now finalized.

Recap: If you ever wanted to have an even closer grip on who is allowed to subclass your classes, there’s now the sealed feature.

public abstract sealed class Shape
permits Circle, Rectangle, Square {...}

This means that while the class is public, the only classes allowed to subclass Shape are Circle, Rectangle and Square.

Foreign Function & Memory API (Incubator)
A replacement for the Java Native Interface (JNI). Allows you to call native functions and access memory outside the JVM. Think C calls for now, but with plans for supporting additional languages (like C++, Fortran) over time.

Deprecating the Security Manager
Since Java 1.0, there had been a Security Manager. It’s now deprecated and will be removed in a future version.

The main changes of the Java 18 release are:

UTF-8 by Default
If you tried, e.g. reading in files without specifying an explicit character ending, the operating system encoding was used in previous Java versions (e.g. UTF-8 on Linux and macOS, and Windows-1252 on Windows). With Java 18 this changed to UTF-8 by default.

Simple Web Server
Java 18 now comes with a rudimentary HTTP server, that you can start with: jwebserver

The main changes of the Java 19 release are:

Java 19 added a couple of exciting features, like Virtual Threads and the new Foreign Function & Memory API, as well as Structured Concurrency and the Vector API — but they are all in preview mode, thus subject to change across the next releases.

The main changes of the Java 20 release are:

Apart from some smaller features, Java 20 mainly iterated on previously introduced preview features: Scope Values, Record Patterns, Pattern Matching for switch, Foreign Function & Memory API, Virtual Threads & Structured Concurrency. All of them are work-in-progress, i.e. haven’t been finalized yet.

The main changes of the Java 21 release are:

Java 21 has arrived in a production release with 15 features including virtual threads, a generational Z garbage collector, and a key encapsulation mechanism API. Few of them are listed out below:

  • Language Feature
  • Libraries Improvements
  • Performance Improvements
  • Tools Improvements
  • Java Emoji Support Tools
  • Enhanced Lifecycle Management with HttpClient
  • Enhanced Repeated Appending in StringBuilder and StringBuffer
  • Advancing Java collections with Sequenced Interface

The main changes of the Java 22 release are:

Unnamed variables and patterns
Launch multi-file source-code programs
Stream Gatherers
String templates
Statements before super
Structured concurrency
Class-file api (preview)
Foreign Function & Memory API
Region pinning for G1
Vector api (seventh incubator)
Scoped values (second preview)
Scoped values
Other changes in java 22

--

--