Java 17 for developers
=>More expressive, less verbose
There are two language features:
- Sealed classes
- Pattern matching for switch (Preview)
- Allow the author of a class or interface to control which code is responsible for implementing it.
- Provide a more declarative way than access modifiers to restrict the use of a superclass.
- Support future directions in pattern matching by underpinning the exhaustive analysis of patterns.
Here a simple example:
A class is sealed by applying the sealed modifier to its declaration.
Then the permits clause specify the classes that can extend it.
Every permitted sub class must directly extend the sealed class.
And every permitted sub class must choose a modifier to describe how it continue the sealing initiated by the super class.
It could be final and allow no further sub classing:
It could in turn be sealed which means it will have it own set of permitted classes:
Or it can be non-sealed.
A sealed class can not prevent permitted classes from doing this.
One and only one of this modifier must be used by each permitted sub class.
Java lang class will get two new methods that call using reflection will be able to determine if a class or interface is sealed.
And if so get a list of permitted classes.
Pattern Matching for switch Preview
Enhance the Java programming language with pattern matching for switch expressions and statements.
Pattern matching on switch allows an expression to be tested against a number of patterns, each with a specific action, so that complex data-oriented queries can be expressed concisely and safely
- Allow patterns to appear in case labels
- Introduces case null statement
Current switch statement works on a few types: numeric, enum and strings.
If we want to use patterns to check for a certain number of possibilities, we need to use a chain of 'if else' statements.
Using pattern matching in a switch, we can make this clearer.
Remember that the case statements has to be exhaustive so in most cases, you will have to add a default value.
But there is one more thing missing here.
Traditionnally, switch statements and switch expressions throw a NullPointerException if the selected expression evaluates to null.
Testing for null, it outside the switch statement:
But now that case label will allow type pattern, we can add a null case to the switch statement:
This makes the code easier to read and maintain.
After a successful pattern match, we often need further tests which can lead to cumbersome code like this:
The desired test: if o is a String of length 1 is split between case and if statement.
We can improve readability if the pattern supports combination of pattern and boolean expression:
First case matches for string of length 1. Second case matches strings of other lengths.
Pattern matching for switch
There are a couple of new gotchas with the rise of pattern matching for switch.
Dominance of pattern labels
The first one is that a pattern could dominate later patterns.
It is a compile-time error if a pattern label in a switch block is dominated by an earlier pattern :
It is possible to have an expression match multiple labels in a switch block.
This is allowed but it must be placed in the right order.
The first example here is very similar to the previous one but with the order reversed:
Since the first label will catch all strings including strings of length one, the second label is never reached.
It is dominated by an earlier case.
This will result in a compile time error.
No fall through allowed when declaring a pattern variable
An other possible error, it to have a fall through when declaring a pattern variable:
In this example, if the variable o was of type Character, the code would print 'character'.
But then, as there is no reasonable break statements, execution will flow to the next case label.
Since the variable i declared in the second pattern would not have been initialized, we get an error.
It is therefore a compile-time error to allow flow through to a case that declares a pattern.
For infer a label that doesn't declare a pattern, it is fine.