Contents:
Java 17 is the newest long term support (LTS) release since Java 11. In the past 6 Java versions there have been various changes implemented, and when considering switching onto the latest LTS, it’s nice to have a quick overview of what’s changed.
So in this blog post we’ll be going over some of the key changes. Each item has it’s related JEP which contains even more details about the change involved and the thought process behind it, so if any change stands out to you, you can find out more.
New features
Pattern Matching for instanceof JEP 394 – Added in Java 16
First up is a nice change to reduce boilerplate code, Pattern Matching has been added for use with instanceof
calls. No longer do you have to check if an object is in instance of a class & then cast the object into that same class immediately after, instead, just add the variable name at the end of the statement & Java will set up the scoped variable for you to use.
For example:
if (obj instanceof String s) {
System.out.println(s.toLowerCase());
}
Records JEP 395 – Added in Java 16
Another change that aims to reduce boilerplate is the addition of records. In situations where you find yourself making a new class for the sole purpose of storing data, you may now be able to use records instead. They are transparent carriers of immutable data that come with all getters/setters/equals/toStrings already generated for you keeping the code that you need to write, simple and clean.
For example:
public record RecordName (DataType a, ...) {}
Sealed Classes JEP 409 – Added in Java 17
To add more control with access to your classes/interfaces, use of the sealed
keyword. This new keyword allows for you to whitelist which classes are permitted to extend your implementation, any other attempt to extend the class with be refused. This is so that a superclass can be made widely accessible but not widely extensible. This new approach is also hoped to be a foundation that can then be used in new future features where pattern matching could potentially be used, such as switch expressions (see JEP 406)
An example would be:
public abstract sealed class ClassName permits ChildClass1, ChildClass2 {}
Switch Expressions JEP 361 – Added in Java 14
Speaking of switch expressions, this feature adds some new variety on how you can use switches. Taking inspiration from more functional approaches to programming, the switch expression in the new option on the approach, removing the need for breaks, allowing for the option for returning of values & ensuring the list is exhaustive. It adds a new keyword yield that is used to return a result to the caller of the expression and allow for multiple labels to use the same path.
This is best shown with an example:
int result = switch (arg) {
case LABEL1 -> 1;
case LABEL2, LABEL3 -> 2;
default -> {
int k = proccessArg(arg);
int defaultResult = customMethod(k);
yield mostSuitable(defaultResult, k);
};
};
(Note that both LABEL2
& LABEL3
will return 2
& that the default uses yield paired with custom code in order to achieve the desired output).
[Preview] Switch Pattern Matching JEP 406 – In preview for Java 17
With the addition of Switch expressions & the concept of pattern matching being added, there was new potential to add to the switch expressions further and add in the functional style of pattern matching with a switch expression. This allows for you to provide an object to a switch expression, and depending on the class adjust the behaviour accordingly. In order to handle potential exceptions, you are also able to test for null in the switch so that the statement can be exhaustive.
See it in use:
switch (o) {
case String s -> System.out.println("String");
case Integer i -> System.out.println("Integer");
case String[] sa -> System.out.println("Array of Strings of length" + sa.length);
case null -> System.out.println("null");
default -> System.out.println("Something else");
}
It also adds a new approach of a Guarded Pattern, which allows us to add a condition for a specific case:
switch (num) {
case Integer i && i > -1 -> System.out.println("Positive Integer");
default -> System.out.println("Not a Positive Integer");
}
This means that when using a switch, you no longer have to rely on falling through, which scales very poorly once you need to do it for more than one case.
Text Blocks JEP 378 – Added in Java 15
Ever find that adding in string literals that span multiple lines is a pain or is too messy? Well text blocks are the new syntax added that allows you to just do that. It’s added by surrounding the text with """
on either side. It functions in a similar way to a String literal, but does not need "
to be escaped or \n
to be explicitly stated.
String textBlock = """
Hello, this is a
multi-line
TextBlock that was added in Java 15
""";
System.out.println(textBlock);
Packaging Tool JEP 392 – Added in Java 16
Another useful tool that has been added since 11 is the packaging tool. If you’re interested in creating platform specific installers/executables, the new packaging tool allows you to do just that.
The supported outputs are:
– Linux: deb and rpm
– macOS: pkg and dmg
– Windows: msi and exe
If you’re using a modular application, the tool is also able to optimize this process even further. It can provide an executable version of Java and remove any of the unused modules.
Changes
Value-Based Classes JEP 390 – Changed in Java 16
In preparation for the Valhalla Project Wrapper Classes like Integer
, Double
, Boolean
, etc. are being updated to be Value-based. This means that you should not be creating instances of these classes or treating them as Objects.
As such, you should be avoiding using !=
in order to see if 2 instances of these Objects are different.
e.g.
public boolean integerCompare(Integer a, Integer b) {
return a != b;
}
You should also not be using the new
keyword to create new instances, but instead us implicit boxing or calls to valueOf
instead.
Integer a;
// Do not use
a = new Integer(14); // Deprecated method
// Instead use
a = 14; // implicit boxing
a = Integer.valueOf(14); // valueOf calls
Lastly any attempt to synchronize on these instances may produce an exception on newer versions of Java.
Boolean b = false;
synchronized (b) { ... } // Do not do this
If you require any of the above functionality, consider looking into using Object
or AtomicReference
.
Always-Strict Floating-Point Semantics JEP 306 – Changed in Java 17
This change is made to help Math
and StrictMath
more consistent with their floating point semantics as the original implementation was added for architecture that is no longer relevant. This is an under the hood change that end users shouldn’t need to worry about.
Hidden Classes JEP 371 – Changed in Java 15
Hidden classes are another under the hood change that allows for classes to be used in an encapsulated manner where they cannot be used directly by bytecode of other classes, and instead relies on being loaded via reflection. These are primarily useful for run-time generated classes and allows for some stronger access control in this use-case. It should be noted that they are not anonymous and can still be seen with Class::getName
.
NullPointerException JEP 358 – Changed in Java 14
Ever get a NullPointerException
stacktrace that points to a specific line, but not only to find that the line has various variables that could have been the cause? Since Java 14 NullPointers will do their best to inform you which variable it is that is null
For example
obj1.coord.x.compare(obj2.coord.y);
could tell you if obj2.coord
is null when trying to access the value of y
.
ZGC / Shenandoah GC JEP 377 / JEP 379 – Changed in Java 15
Both Garbage Collectors have now matured to product features from experimental features.
New macOS Rendering Pipeline JEP 382 – Changed in Java 17
Following the new Rendering Pipeline being added to macOS, Java 17 has implemented the Metal framework as an alternative to the existing pipeline.
EdDSA JEP 339 – Changed in Java 15
New Cryptographic Signature Algorithm is available. This is based of the Edwards-Curve Digital Signature Algorithm that is described in RFC 8032.
New PseudoRandom Number Generators (PRNGs) JEP 356 – Changed in Java 17
This change adds 4 new Interfaces to make the process of switching out PRNGs easier, they are:
– SplittableRandomGenerator
– JumpableRandomGenerator
– LeapableRandomGenerator
– ArbitrarilyJumpableRandomGenerator
Some of these interfaces have new generation methods implemented.
Context-Specific Deserialization Filters JEP 415– Changed in Java 17
Java 9 added in new functionality that allowed for data streams to be validated before being deserialized. The problem with is was that it was implemented for a single static JVM-wide deserialization filter (which did not scale very well). This change adds per-stream filters that does not require every stream creator to participate and a configurable JVM-wide filter factory.
Foreign Function and Memory API & Vector API (Incubating) JEP 412 / JEP 414 – Changed in Java 17
These 2 features are currently incubating, so their API’s are experimental and require their modules to explicitly be added in order to try. Both JEPs are proposed as part of Project Panama as ways to improve the handling of foreign APIs in Java. If this sounds of interest, check out the JEP for more details, as these changes are experimental and are not ready for preview just yet.
Deprecations/Removals
Biased locking JEP 374 – Deprecated in Java 15
Biased locking was an optimization technique that used to be effective. However, over time it has primarily only helped the performance of legacy code, with switching to new classes implementations results in better performance. It was primarily deprecated due to its difficulty to maintain.
ParallelScavenge + SerialOld GC combination JEP 366 – Deprecated in Java 14
Specifically the combination of both the ParallelScavenge + SerialOld Garbage Collectors have been deprecated due to low usage and the significant difficulty to maintain. It is advised to just use either GC on their own.
Applet API JEP 398 – Deprecated in Java 17
The Applet API has been deprecated since Java 9, but was not flagged for removal. Java 17 has now set it for removal.
Security Manager JEP 411 – Deprecated in Java 17
The deprecation of the SecurityManager
does not mean Java has given up on security, it found that the risks the class prevents were no longer significant and the things it can’t protected against things that are significant.
Concurrent Mark Sweep (CMS) GC JEP 363 – Removed in Java 14
This Garbage Collection method has been surpassed by other GCs and was marked for removal back in Java 9. It has since been removed.
Experimental AOT/JIT compiler JEP 410 – Removed in Java 17
The experimental feature added in Java 9 is seeing little usage and had a high maintenance cost.
Solaris and SPARC Ports JEP 381 – Removed in Java 15
The support for these ports was acting as a hinderance to projects like Loom, Valhalla & Panama so were marked for removal in Java 14, and then removed in Java 15.
RMI Activation JEP 407 – Removed in Java 17
The activation mechanism of RMI was effectively obsolete and imposed a burden on maintenance. It was already optional in Java 11 & no feedback was sent when it was deprecated for removal in Java 15.
Nashorn JavaScript Engine JEP 372 – Removed in Java 15
The Nashorn JavaScript Engine was a complete implementation of the ECMAScript-262 5.1 standard but with frequent updates to the spec and new options like GraalVM’s direct JavaScript access, it was deprecated due to its difficulty to maintain. It was deprecated in Java 11 and removed in Java 15.
Pack200 Tools and API JEP 367 – Removed in Java 14
The Pack200 was used to optimise JAR files, however was surpassed by Java 9 features like modules and compression schemes. It was deprecated for removal in Java 11 and has since been removed.
Our software libraries allow you to
Convert PDF to HTML in Java |
Convert PDF Forms to HTML5 in Java |
Convert PDF Documents to an image in Java |
Work with PDF Documents in Java |
Read and Write AVIF, HEIC, WEBP and other image formats |