3 Enhanced Deprecation

The semantics of what deprecation means includes whether an API may be removed in the near future.

If you are a library maintainer, you can take advantage of the updated deprecation syntax to inform users of your library about the status of APIs provided by your library.

If you are a library or application developer, you can use the jdeprscan tool to find uses of deprecated JDK API elements in your applications or libraries.

Deprecation in the JDK

Deprecation is a notification to library consumers that they should migrate code from a deprecated API.

In the JDK, APIs have been deprecated for widely varying reasons, such as:
  • The API is dangerous (for example, the Thread.stop method).

  • There is a simple rename (for example, AWT Component.show/hide replaced by setVisible).

  • A newer, better API can be used instead.

  • The API is going to be removed.

In prior releases, APIs were deprecated but rarely ever removed. Starting with JDK 9, APIs may be marked as deprecated for removal. This indicates that the API is eligible to be removed in the next release of the JDK platform. If your application or library consumes any of these APIs, then you should plan to migrate from them soon.

For a list of deprecated APIs in the current release of the JDK, see the Deprecated API page in the API specification.

How to Deprecate APIs

Deprecating an API requires using two different mechanisms: the @Deprecated annotation and the @deprecated JavaDoc tag.

The @Deprecated annotation marks an API in a way that is recorded in the class file and is available at runtime. This allows various tools, such as javac and jdeprscan, to detect and flag usage of deprecated APIs. The @deprecated JavaDoc tag is used in documentation of deprecated APIs, for example, to describe the reason for deprecation, and to suggest alternative APIs.

Note the capitalization: the annotation starts with an uppercase D and the JavaDoc tag starts with a lowercase d.

Using the @Deprecated Annotation

To indicate deprecation, precede the module, class, method, or member declaration with @Deprecated. The annotation contains these elements:

  • @Deprecated(since="<version>")

    • <version> identifies the version in which the API was deprecated. This is for informational purposes. The default is the empty string ("").

  • @Deprecated(forRemoval=<boolean>)

    • forRemoval=true indicates that the API is subject to removal in a future release.

    • forRemoval=false recommends that code should no longer use this API; however, there is no current intent to remove the API. This is the default value.

For example: @Deprecated(since="9", forRemoval=true)

The @Deprecated annotation causes the JavaDoc-generated documentation to be marked with one of the following, wherever that program element appears:
  • Deprecated.

  • Deprecated, for removal: This API element is subject to removal in a future version.

The javadoc tool generates a page named deprecated-list.html containing the list of deprecated APIs, and adds a link in the navigation bar to that page.

The following is a simple example of using the @Deprecated annotation from the java.lang.Thread class:

public class Thread implements Runnable {
	... 
	@Deprecated(since="1.2")
	public final void stop() {
		...
	}
	...

Semantics of Deprecation

The two elements of the @Deprecated annotation give developers the opportunity to clarify what deprecation means for their exported APIs (which are APIs that are provided by a library that are accessible to code outside of that library, such as applications or other libraries).

For the JDK platform:
  • @Deprecated(forRemoval=true) indicates that the API is eligible to be removed in a future release of the JDK platform.

  • @Deprecated(since="<version>") contains the JDK version string that indicates when the API element was deprecated, for those deprecated in JDK 9 and beyond.

If you maintain libraries and produce your own APIs, then you probably use the @Deprecated annotation. You should determine and communicate your policy around API removals. For example, if you release a new library every six weeks, then you may choose to deprecate an API for removal, but not remove it for several months to give your customers time to migrate.

Using the @deprecated JavaDoc Tag

Use the @deprecated tag in the JavaDoc comment of any deprecated program element to indicate that it should no longer be used (even though it may continue to work). This tag is valid in all class, method, or field documentation comments. The @deprecated tag must be followed by a space or a newline. In the paragraph following the @deprecated tag, explain why the item was deprecated, and suggest what to use instead. Mark the text that refers to new versions of the same functionality with an @link tag.

When it encounters an @deprecated tag, the javadoc tool moves the text following the @deprecated tag to the front of the description and precedes it with a warning. For example, this source:
  /**
   * ...
   * @deprecated  This method does not properly convert bytes into
   * characters.  As of JDK 1.1, the preferred way to do this is via the
   * {@code String} constructors that take a {@link
   * java.nio.charset.Charset}, charset name, or that use the platform's
   * default charset.
   * ...
   */
   @Deprecated(since="1.1")
   public String(byte ascii[], int hibyte) {
      ...

generates the following output:

@Deprecated(since="1.1")
public String​(byte[] ascii, 
              int hibyte)
Deprecated. This method does not properly convert bytes into characters. As of 
JDK 1.1, the preferred way to do this is via the String constructors that take a 
Charset, charset name, or that use the platform's default charset.

If you use the @deprecated JavaDoc tag without the corresponding @Deprecated annotation, a warning is generated.

Notifications and Warnings

When an API is deprecated, developers must be notified. The deprecated API may cause problems in your code, or, if it is eventually removed, cause failures at run time.

The Java compiler generates warnings about deprecated APIs. There are options to generate more information about warnings, and you can also suppress deprecation warnings.

Compiler Deprecation Warnings

If the deprecation is forRemoval=false, the Java compiler generates an "ordinary deprecation warning". If the deprecation is forRemoval=true, the compiler generates a "removal warning".

The two kinds of warnings are controlled by separate -Xlint flags: -Xlint:deprecation and -Xlint:removal. The javac -Xlint:removal option is enabled by default, so removal warnings are shown.

The warnings can also be turned off independently (note the "–"): -Xlint:-deprecation and -Xlint:-removal.

This is an example of an ordinary deprecation warning.

$ javac src/example/DeprecationExample.java	
Note: src/example/DeprecationExample.java uses or overrides a deprecated API.	
Note: Recompile with -Xlint:deprecation for details.	

Use the javac -Xlint:deprecation option to see what API is deprecated.

$ javac -Xlint:deprecation src/example/DeprecationExample.java	
src/example/DeprecationExample.java:12: warning: [deprecation] getSelectedValues() in JList has been deprecated	
   Object[] values = jlist.getSelectedValues();	
                     ^	
1 warning	

Here is an example of a removal warning.

public class RemovalExample {
    public static void main(String[] args) {
        System.runFinalizersOnExit(true);
    }
}
$ javac RemovalExample.java
RemovalExample.java:3: warning: [removal] runFinalizersOnExit(boolean) in System 
has been deprecated and marked for removal
        System.runFinalizersOnExit(true);
              ^
1 warning
==========

Suppressing Deprecation Warnings

The javac -Xlint options control warnings for all files compiled in a particular run of javac. You may have identified specific locations in source code that generate warnings that you no longer want to see. You can use the @SuppressWarnings annotation to suppress warnings whenever that code is compiled. Place the @SuppressWarnings annotation at the declaration of the class, method, field, or local variable that uses a deprecated API.

The @SuppressWarnings options are:
  • @SuppressWarnings("deprecation") — Suppresses only the ordinary deprecation warnings.

  • @SuppressWarnings("removal") — Suppresses only the removal warnings.

  • @SuppressWarnings({"deprecation","removal"}) — Suppresses both types of warnings.

Here’s an example of suppressing a warning.

   @SuppressWarnings("deprecation")
   Object[] values = jlist.getSelectedValues();

With the @SuppressWarnings annotation, no warnings are issued for this line, even if warnings are enabled on the command line.

Running jdeprscan

jdeprscan is a static analysis tool that reports on an application’s use of deprecated JDK API elements. Run jdeprscan to help identify possible issues in compiled class files or jar files.

You can find out about deprecated JDK APIs from the compiler notifications. However, if you don’t recompile with every JDK release, or if the warnings were suppressed, or if you depend on third-party libraries that are distributed as binary artifacts, then you should run jdeprscan.

It’s important to discover dependencies on deprecated APIs before the APIs are removed from the JDK. If the binary uses an API that is deprecated for removal in the current JDK release, and you don’t recompile, then you won’t get any notifications. When the API is removed in a future JDK release, then the binary will simply fail at runtime. jdeprscan lets you detect such usage now, well before the API is removed.

For the complete syntax of how to run the tool and how to interpret the output, see The jdeprscan Command in the Java Development Kit Tool Specifications.