Java Deprecated APIs and SuppressWarnings "deprecation" - practical approach

Step 1: Announce the removal

One may think that deprecating an API means announcing it will be removed, but this is not the only use case (as described in relevant articles of e.g. Java 7 and Java 9):

  • 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 deprecated API is going to be removed.

To further complicate things, before Java 9, no deprecated API in the JDK was ever removed (see 20 Years Of Java Deprecation), so it is understandable if developers do not take deprecation seriously - neither in the JDK nor elsewhere.

Therefore, you need to communicate clearly that the API is really, really going to be removed. The way to do this depends on the version of Java your API is compiled with.

Java 8 or lower

In these Java versions, there is no formal way to explicitly distinguish the various deprecation use cases. The best you can do is adding the Javadoc tag @deprecated and not only giving the reason of deprecation and listing alternatives, but also explicitly announcing your intention to remove the API.

Java 9 or above

Since Java 9, with Enhanced Deprecation, you can now write

@Deprecated(forRemoval=<boolean>)

to explicitly document your intention. I think that together with Javadoc @deprecated (which should detail the reason for deprecation and list alternatives), this standardized flag is a fair warning.

With this flag set to true, the compiler will warn for each use of the deprecated element like this:

YourClass.java:<line>: warning: [removal] <method> in <class> has been
deprecated and marked for removal

This warning is enabled by default (instead of having to be enabled with -Xlint:deprecation) and is not suppressed with @SuppressWarnings("deprecation"). Instead, one would have to suppress it with the new @SuppressWarnings("removal"), which might make developers think twice about doing so without a really good reason.

Additionally, you can explicitly state the library version which introduced the deprecation with

@Deprecated(since="<version>")

Seeing this in Javadoc or the sources can help developers assess how urgent it is update their code.

Step 2a: Runtime warning

If feasible for the situation, add a runtime reminder: when the deprecated API is used, have it log a warning to the console or log file (using whatever logging mechanism you use) announcing that this will no longer work with the next major release. To avoid spam, you could only log that once (e.g. private static boolean warningLogged).

Step 2b: Static code analysis

Static code analyzers like SonarQube (also available as a hosted service) can be set up to flag each of these warnings. The SonarQube rule "deprecated code should not be used" should even work if the compiler's deprecation usage warning is suppressed.

SonarQube also tracks when a certain issue (i.e. a rule violation) was introduced (based on version control) and you can interactively filter its issue lists based on that date. For example, you could list all usages of deprecated code that have been in your code base for over a year so that you can prioritize work on fixing them.

Step 3: Remove the API

Not actually removing the API would give your API users the impression that they don't need to bother changing their code.


A deprecated API is not useful just as far as it is annotated with @Deprecated. If the API clients can still successfully use it after years of it being marked as deprecated, then it's right to say that the API provider isn't helping them in any practical way.

Is there a practical solution to this problem?

Yes: let deprecation mean deprecation and after a grace period, make the deprecated API unavailable, if removal is the correct way to deal with it. If, for example, you deprecate an API with security risks, not removing it in a future release makes deprecation useless and can be seen as contributing to the problem.

The @Deprecated annotation is little more than documentation, which, even as you noted, other developers can simply ignore.

Java 9+ deprecation is perhaps more informative, but the end decision is still up to the developer consuming the API, which doesn't solve the problem.


Is there a practical solution to this problem?

Practical from whose perspective?

From the perspective of developers who routinely ignore / suppress deprecation warnings, they already have their "solution" ... which is to ignore the problem. But the flipside is that other people can't stop them from doing that. But the flipside of the flipside is that ... ultimately ... it is not other peoples' business.

From the perspective of developers who wish to deprecate the APIs that they maintain, they already have a solution. Just do it. Then follow through with the next step by actually removing deprecated APIs. The flipside is that it will annoy some people, and other people will be burned. (Especially people who routinely ignore / suppress deprecation warnings. But see above: that is their problem.)

From the perspective of someone whose concern / responsibility it is to maintain the code quality / integrity of an organization's codebase, yes there is a problem. But the solution is relatively strait-forward:

  • Forbid code the use of @suppress("deprecation")`.
  • Forbid build scripts that turn off deprecation warnings.
  • Enforce the above in via SCI server plugins, custom style-checker rules, or (if you want to be crude) by "grepping" the source code.
  • Take a (metaphorical) big stick to programmers who are repeat offenders.

Are there any planned JRE/JDK features that might help with this situation?

As noted, Java 9+ enhanced annotation support (see JEP 277):

  • provides more informative deprecation tagging, and
  • provides a tool (jdeprscan) for scanning for deprecation violations against the Java SE APIs.