Saturday, March 24, 2018

Forward-Looking with Java's @Deprecated

I have occasionally run into a situation in which I have needed to introduce a new API or construct for others to try out, but have known that it might change based on others' feedback after some use of it. In such cases, I've wanted to somehow annotate the construct to warn other developers of the tentativeness of this newly added construct. There are several alternatives that I have considered in these cases.

Third-party Annotation

The Javadoc documentation for Guava's @Beta annotation states:

Signifies that a public API (public class, method or field) is subject to incompatible changes, or even removal, in a future release. An API bearing this annotation is exempt from any compatibility guarantees made by its containing library. Note that the presence of this annotation implies nothing about the quality or performance of the API in question, only the fact that it is not "API-frozen."

This explanation of the use of @Beta seems to imply this is a good fit for a "new" construct that may be removed. I talked more about this annotation in the blog post "Two Generally Useful Guava Annotations".

Other considerations when using a third-party library's annotation is that the third-party library must be included on one's classpath and that there is typically no out-of-the-box support in the most popular Java IDEs to indicate special treatment of the construct annotated with the annotation.

Custom Annotation

If one is not using the library with the annotation for any other reason, it can seem a bit heavy to add a new library dependency simply for an annotation when it's relatively straightforward to write one's own custom annotation. I have written about writing a custom @Unfinished annotation before and that post discussed how to create corresponding custom IDE inspections in NetBeans 8.0.2 and IntelliJ IDEA 14.0.3 for this custom annotation.

The following code listing provides an example of a custom annotation one could use for this purpose.

@Preview Annotation

package dustin.examples.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Preview
{
   /**
    * Anticipated release in which Preview status will no longer apply.
    *
    * @return Anticipated release of feature
    */
   String transition() default "";

   /**
    * Version in which this preview feature was introduced.
    *
    * @return Release in which this preview feature was introduced.
    */
   String since() default "";

   /**
    * Reasons this construct is considered "preview."
    *
    * @return Reasons this construct is considered preview.
    */
   String[] reasons() default {};
}

The custom annotation lacks any out-of-the-box support in the popular Java IDEs.

Comments Only

Annotations don't necessarily need to be used and simple comments (Javadoc or otherwise) could explain that a particular construct is preliminary and might go away. However, comments are weaker in many ways than annotations in terms of communicating intent. It is much more difficult to have an IDE or other tooling parse comments than to process annotations.

@Deprecated Annotation and @deprecated Javadoc Tag

One can use @Deprecated to annotate a deprecated construct with a standard annotation that IDEs, tools, and scripts can easily process. Unfortunately, the @Deprecated annotation never got the full support I had hoped it would get for more specifically specifying why something was deprecated when it was decided to make the JDK 9 enhanced @Deprecated much less ambitious. The Javadoc @deprecated tag can be used to document that the deprecation is actually for a "new" construct that might go away, but also might not go away. The @Deprecated annotation and the @deprecated Javadoc tag can be removed if it's decided to keep the "preview" construct.

Although the @Deprecated annotation and @deprecated Javadoc tag enjoy benefits from being standards that include built-in IDE support and awareness among most Java developers, it can still feel a bit inappropriate to use these to mark a new construct that may go away, but may stick around. The "When to Deprecate" section of the document "How and When To Deprecate APIs" states, "When you design an API, carefully consider whether it supersedes an old API." It further lists three reasons for deprecation which are "insecure, buggy, or highly inefficient", "going away in a future release", and "encourages bad coding practices".

I'm not the only one who thinks of "deprecation" as marking something likely to be removed or that should not be used. Nicolas Fränkel outlines the feature lifecycle in Java and explains that deprecation in Java is "a bold and clear statement to everyone that a feature version has no future, at least in its current form."

In the jdk-dev mailing list message "JEP 12: Treatment of standard APIs supporting preview features," Alex Buckley writes:

We'd like to use deprecation-for-removal-at-birth as the way to flag "this API is intimately connected to a preview feature". If the preview feature becomes permanent, then the deprecation would be removed. This jump from terminal-deprecation to no-deprecation is novel, but not mad -- deprecation has a variety of meanings, and its historical use in the JDK is not a good guide to anything.

Buckley also cites a paragraph from JEP 277 ("Enhanced Deprecation") regarding use of the deprecation mechanisms (I have highlighted the same portion Buckley emphasized):

Deprecation is a technique to communicate information about the life cycle of an API: to encourage applications to migrate away from the API, to discourage applications from forming new dependencies on the API, and to inform developers of the risks of continuing dependence upon the API.

The JDK 9-introduced "enhanced" @Deprecated annotation can help a bit in this situation (that Buckley termed "deprecation-for-removal-at-birth") via its newly added "since" and "forRemoval" elements. Specifying the @Deprecated annotation's forRemoval() as false and specifying its since as the same version as the Javadoc @since tag might help developers to see that the construct was deprecated from the beginning with no current plans to remove it. For such an approach to be most effective, it'd probably be write to explicitly state forRemoval as false rather than relying on its implicit default.

It may be that we Java developers will need to start thinking of @Deprecated and @deprecated a bit differently than in the past. Although the @Deprecated annotation and @deprecated Javadoc tag still "inform" us of "the risks of continuing dependency" upon the annotated/described construct, it may be incorrect to assume that such a construct is necessarily going away at some point in the future. If we get used to this alternate meaning in deprecated JDK constructs, we'll be more likely to consider using the same approach with our own newly added and still tentative features.

Saturday, March 17, 2018

Raw String Literals Coming to Java

It appears likely that "raw string literals" are coming to Java. JEP 326 ("Raw String Literals") started as Issue JDK-8196004 and was announced as a "new JEP candidate" on March 2. The JEP and associated issue point out that "Java remains one of a small group of contemporary programming languages that do not provide language-level support for raw strings." The JEP and associated issue specifically reference programming languages C, C++, C# ("verbatim"), Dart, Go, Groovy, Haskell, JavaScript, Kotlin, Perl, PHP, Python, R, Ruby, Scala and Swift and the "Unix tools" bash, grep, and sed that were "surveyed for their delimiters and use of raw and multi-line strings."

JEP 326's "Summary" provides an overview of the proposed Java raw string literals: "A raw string literal can span multiple lines of source code and does not interpret escape sequences, such as \n, or Unicode escapes, of the form \uXXXX." The "Motivations" section of this JEP adds, "This JEP proposes a new kind of literal, a raw string literal, which sets aside both Java escapes and Java line terminator specifications, to provide character sequences that under many circumstances are more readable and maintainable than the existing traditional string literal." JEP 326 does not introduce interpolation and, in fact, rules it out in its "Non-Goals" section: "Raw string literals do not directly support string interpolation. Interpolation may be considered in a future JEP."

Multi-line String literals have long been desired in Java. JEP 326 ("Raw String Literals") currently lists several examples of how raw string literals would make it easier to implement common things in Java and these example uses include multi-line strings, operating system file paths, regular expressions, relational database SQL statements, and polyglot (Java+JavaScript).

The current version of JEP 326 states that Java's raw string literals will be denoted via the use of the "backtick" character (`), which is also described in the JEP as \u0060 (Unicode "Grave Accent"), "backquote", and "accent grave". I don't show any examples of the proposed syntax because the JEP already does a nice job of listing these proposed raw string literal examples alongside examples of traditional Java code needed to implement the same thing. This makes it easy to compare the required current syntax to what would be needed in the future to accomplish the same thing if raw string literals are supported.

Support for raw string literals in Java will provide nice convenience for Java developers wishing to write more readable code to support use cases like those described in the JEP. It will provide similar advantages to libraries and even to the JDK code. The core-lib-devs mailing list post "Raw String Literal Library Support" [JDK-8196005] starts a "discussion with regards to RSL library support." (The context of "library support" in this case is the JDK and RSL stands for Raw String Literal.).

In the referenced post Raw String Literal Library Support, Jim Laskey provides a list of methods to potentially add to String to take advantage of raw string literals. These ideas for kicking off discussion include "line support", enhancements to "trim" methods, "margin management", and "escape management". Some of these are facilitated by RSL while others are necessitated by RSL. The cited post provides multiple examples of each of these.

Issue JDK-8198986 points out that "a new JLS section is needed for raw string literals." This issue links to a currently proposed section to be added to the cited Java Language Specification.

Although JEP 326 is still just a "Candidate" and is not associated with a particular release of Java, recent work on it and recent discussion in mailing list posts seeking input related to it lead me to be cautiously optimistic that we'll see multi-line Java strings and other raw string literals coming to Java in a future release.

Tuesday, March 13, 2018

Updates on JavaFX, Valhalla, Data Classes, and Java's Floating-Point

There have been some interesting posts this week and in recent weeks that provide more insight into the future of Java and the JDK.

JavaFX Removed from JDK with JDK 11

In the blog post "The Future of JavaFX and Other Java Client Roadmap Updates," Oracle's Donald Smith announced that "starting with JDK 11, Oracle is making JavaFX easier to adopt by making the technology available as a separate download, decoupled from the JDK." Smith provides a brief history of JavaFX and discusses other motivations for the decision to decouple JavaFX from the JDK.

The "The Future of JavaFX and Other Java Client Roadmap Updates blog post concludes with a reference to the March 2018 Oracle whitepaper "Java Client Roadmap Update." That referenced whitepaper describes "the Java Client" as "consist[ing] of Java Deployment (Applets and Web Start) and Java UI (Swing, AWT and JavaFX) technologies" and then "provides an overview of the current roadmap and recommendations for each technology." About Swing/AWT, this whitepaper states, "Swing and AWT will continue to be supported on Java SE 8 through at least March 2025, and on Java SE 11 (18.9 LTS) through at least September 2026."

Valhalla

Project Valhalla hosts some of the concepts and ideas I most excitedly anticipate for future versions of Java. I have long wanted reified generics (still only listed on the Valhalla Wiki page as "possibly other related topics" to be considered in the future), but also look forward to "value objects." I have written before, in the post "The Value in Project Valhalla," about what makes value objects so exciting.

In a recent post on the core-libs-dev mailing list, Brian Goetz wrote about how Valhalla might one day address "an obvious gap between primitive and reference types in Java." Goetz describes how Java makes it easy to add libraries, but that "the primitive types we have are fixed and we effectively cannot make more." Goetz states that Valhalla's solution to this gap is the introduction of "value types" that "are like classes" in some characteristics, but "are like primitives" in terms of other characteristics. He sums this up as, "Codes like a class, works like an int." Most of this was not new to me thanks to Goetz's and others' earlier posts and articles on value types. However, Goetz points out in this mailing list post a "now obvious" to me consequence of these value types: "Value types let us write new numeric (and other) types as library classes, and get the performance characteristics of primitives." This concept makes me wish we had value types yesterday!

Goetz provides a very rough idea of the timeframe for value types in a future version of the JDK. He writes, "Project Valhalla has been rolling for a few years, and will likely go for a few more until we reach the point where this is practical -- and more after that before value types can fit cleanly into the generic type system." This statement dampens my hopes a bit, but does seem realistic given the magnitude and broad scope of the changes involved.

The "Valhalla EG notes" dated 28 February 2018 provide insight to the current state of Valhalla.

Floating-Point in Java

The Goetz post on how Valhalla might someday allow Java developers to write "their favorite numeric type" as "ordinary user-written libraries" when not already "built into the platform" exists in the context of a mailing list thread about a request user request and statement that "the java language needs to be changed" in relation to "arithmetic underflow and overflow" and "arithmetic approximation" associated with Java's floating-point types. What caught my particular attention (besides Goetz's reference to Valhalla) in this thread is an excellent overview of Java's handling of float-point types provided by Joe Darcy.

In this mailing list message (which would make an outstanding blog post or article), Darcy concisely and thoroughly (hard to do at the same time) lays out the challenges associated with representation of and calculation using floating-point approximations "with pragmatic compromises to facilitate calculation on computers." This post is much more accessible to most of us developers than the 70+ pages of the classic article "What Every Computer Scientist Should Know About Floating-Point Arithmetic."

Darcy also provides guidance on what to expect in future versions of Java's handling of floating-points. He writes (I added the emphasis):

There are no prospects for a fundamental redefinition of the floating-point semantics of the Java language and VM. It is possible a faster and looser mode will be defined at some point, but altering the default is extremely unlikely. Long-term, decimal-based arithmetic (and other kinds of arithmetic) may get better support as a consequence of the features in Valhalla.

The Darcy post is worth reading for its overview of floating-point computations in binary-based computer systems in general and in Java in particular. Darcy concludes the post with a paragraph on expected etiquette on the OpenJDK mailing lists.

Data Classes

In a February 2018 post titled "Data Classes for Java", Goetz "explores possible directions for data classes in the Java Language." Goetz contrasts data classes versus value types (such as pointing out that data classes have identity while value types sacrifice identity to reduce overhead). He also explains why data classes are preferable to tuples and to the "only syntax-deep" "compact syntactic forms for modeling data-oriented classes" such as those provided by Scala (case) and Kotlin (data). Much of this post is on considerations that must be made when designing and implementing data classes in Java.