SKP's Java/Java EE Gotchas: Revisiting Java SE 9 Features, Part 1
In this follow up article, we discuss some of the nuances of Java 9 in the context of potential errors you might encounter.
Join the DZone community and get the full member experience.Join For Free
Preparing for an interview? Want to just revisit Java SE 9 features? Trying to recollect or revise Java SE programming constructs? Let me take you back in time to what was introduced first in Java SE 9? Join me for this tutorial series on Java as we all eagerly await the official release of Java SE 14!
As I promised, I am back with the code samples of my earlier article Java SE 9... What's New? You may refer the earlier article to understand the newly introduced features at a high level. This article provides the code samples for each of the features.
You may download the code samples for the following new features here. (Import as eclipse project, set compiler/environment as Java 9. Run the main class 'Java9Application' to see the output/outcome of the Code Samples.)
I plan to start by re-visiting a Java 8 feature, Default Interface Methods.
You may also enjoy: SKP's Java/Java EE Gotchas: Java SE 9 Features
Default Interface Methods
Whenever there is existing or legacy code that has Interfaces that require the addition of new methods, it breaks existing classes that inherit or implement from this interface, unless the implementation for each of these added methods is provided in the classes. This is not very maintainable code. Even though it's a good practice as from SOLID and other OO paradigms to provide an interface without any implementation — we need to handle and solve the problem as mentioned above. This is where default interface methods come in.
From the example above, the
LegacyPublicInterface in an existing application is already extended by multiple invoice types (for example, in an inventory system). Re-engineering effort requires that each of the invoices have a method to invalidate or remove an Item marked with "OOS." Given such a problem, prior to Java 8, we would have to introduce a new method declaration in the interface and then require that each of the implementing classes implement their own logic for handling this. With default interfaces, the task becomes very simple (the code is now more maintainable and extensible and requires very less effort to change). With the introduction of Default Methods, here are the possibilities:
- Use the Default Method(s) without breaking existing functionality (best use)
- Implementing Class can choose to override these Default Methods
- Abstract Classes can be provided over the Interfaces to override Implementation
Java Language Changes in JDK 9
Private Interface Methods
Interfaces in Java 9 are allowed to have Private Methods. This was done to allow code sharing between non-abstract methods in the Interface. All rules related to ordinary Private modifiers apply to these methods. The point to note is that a method cannot be both private and abstract. It definitely needs to have a method body.
You can observe the usage of the above private method (internally by the new default method) through the following code.
Underscore as A Variable Name Is Not Legal Anymore
Using only the underscore character ("_") as a variable name is not legal anymore. This is because it is marked as a reserved keyword from Java 1.8 (but caused compilation failure only in Java 1.9). This may cause some issues when compiling legacy source code, especially with a necessity to denote some specific resource or entity using the underscore. It may have to be rewritten and may have many related ramifications.
Allow Effectively Final Variables to Be Used as Resources in Try with Resources
Until Java 8, every variable that had to be used within Try with Resources statements was required to be declared within the try statement. Only then can it be used within the try block. This is a limitation for the developer. Hence, in Java 9, this restriction has been removed and any final variable or effectively final (local) variable can be used inside the try block. All other rules as applicable to Try with Resources continue. Effectively Final means the variable is not changed after it has been initialized.
@SafeVarargs is Allowed on Private Instance Methods
Using non-reifiable variable argument parameters in a method can cause multiple warnings when trying to compile code, such as:
@SafeVarargswas introduced to suppress such warnings on unchecked or unsafe operations. By using this, the developer is signalling to the compiler that he has made sure that there will be no heap pollution (such as unsafe
Prior to Java 9,
@SafeVarargsis allowed on non-overridable methods such as in static methods, final instance methods and constructors. Note that the annotation will throw an error if it is used in fixed arity methods. In Java 9,
@SafeVarargscan be used on private instance methods.
Allow Diamond with Anonymous Classes If Inferred Type's Argument Type is Denotable
"Using diamond with anonymous inner classes is not supported since doing so in general would require extensions to the class file signature attribute to represent non-denotable types, a de facto JVM Change."
"Internally, a Java compiler operates over a richer set of types than those that can be written down explicitly in a Java program. The compiler-internal types which cannot be written in a Java program are called non-denotable types. Non-denotable types can occur as the result of the inference used by diamond. Therefore, using diamond with anonymous inner classes is not supported since doing so in general would require extensions to the class file signature attribute to represent non-denotable types, a de facto JVM change. It is feasible that future platform versions could allow use of diamond when creating an anonymous inner class as long as the inferred type was denotable."
Core Library Changes in Java 9
JEP 102: Process API Updates
ProcessHandle. Also, we can retrieve information about the currently running Java process and info (inner class of
ProcessHandle) class/object that contains details on the process. We can also enlist or return a snapshot of all currently running processes in the system.
With an eye on maintainable and more informative code, the developer-defined deprecation now allows us to mark deprecation with additional elements of information like forRemoval and since. The forRemoval allows allows to mark that this item may be removed in the future versions of Java and since provides information about when it was first introduced.
This addition makes it convenient for the Developer to create Immutable Collections out of existing interfaces, be it Set, Map or List. A static factory method
of() added to Set, Map, and List. It is important you understand the following (even though it'sconsistent with previous versions of Java):
- They are structurally immutable.
- They disallow null elements or null keys.
- They are serializable if all elements are serializable.
- They reject duplicate elements/keys at creation time.
- The iteration order of set elements is unspecified and is subject to change.
- They are value-based. Factories are free to create new instances or reuse existing ones. Therefore, identity-sensitive operations on these instances (reference equality (==), identity hash code, and synchronization) are unreliable and should be avoided. They are serialized as specified on the serialized form page.
You may download the code samples for the following new features here. (Import as an Eclipse project, set the compiler/environment as Java 9. Make sure that you have Java 9/JDK 9 installed on your system. Run the main class
Java9Application to see the output/outcome of the code samples.)
Check out the Eclipse console output provided below from running the
Java9Application (refer attached code samples). Please refer to the individual classes, provided for each of the features to understand the features better. Go ahead, add, modify, delete to experiment with all of the new Java 9 features.
Happy Coding with Java 9!
Opinions expressed by DZone contributors are their own.