Suppress Deprecated Import Warning in Java

Suppress deprecated import warning in Java

To avoid the warning:
do not import the class

instead use the fully qualified class name

and use it in as few locations as possible.

How to get rid of deprecation warnings when providing backwards compatibility?

In order to get rid of such deprecation warnings, when providing backwards compatibility,
one has to remove the import, to which one cannot apply @SuppressWarnings("deprecation"):

// import android.net.NetworkInfo;

And then use it's fully qualified class name android.net.NetworkInfo instead of NetworkInfo. The point is, that one can only apply @SuppressWarnings("deprecation") to methods, but not imports.

What do @SuppressWarnings(deprecation) and (unused) mean in Java?

The @SuppressWarnings annotation disables certain compiler warnings. In this case, the warning about deprecated code ("deprecation") and unused local variables or unused private methods ("unused"). This article explains the possible values.

Can @SuppressWarnings(deprecation) apply to the use of a deprecated interface without applying to the whole class?

The @SuppressWarnings annotation can only be used at the point of a declaration. Even with the Java 8 annotation enhancements that allow annotations to occur in other syntactic locations, the @SuppressWarnings annotation can't be used where you need it in this case, that is, at the point where a deprecated interface occurs in the implements clause.

You're right to want to avoid putting @SuppressWarnings on the class declaration, since that will suppress possibly unrelated warnings throughout the entire class.

One possibility for dealing with this is to create an intermediate interface that extends the deprecated one, and suppress the warnings on it. Then, change the uses of the deprecated interface to the sub-interface:

@SuppressWarnings("deprecation")
interface SubBaz extends DeprecatedBaz { }

public class Foo ... implements SubBaz ...

This works to avoid the warnings because class annotations (in this case, @Deprecated) are not inherited.

How to avoid deprecation warnings when @SuppressWarnings(deprecation) doesn't work?

I'm sorry to say that I don't have a solution to the problem you're facing, though as you've observed, there has been some progress. We've been trying to get rid of all the Java compilation warnings in the JDK itself, and this has been a long, difficult process. During JDK 8 development in 2011 I helped kick off the warnings cleanup effort and I later co-presented a JavaOne talk (slides and audio) on the subject.

More recently, my colleage Joe Darcy has continued the warnings cleanup work and has worked through the different warnings categories and has finally reached deprecation warnings. As you noted, there have been some bugs in the compiler's handling of suppression of deprecation warnings, such as JDK-6480588 which was fixed in JDK 8. Unfortunately, it is still not possible in JDK 8 to suppress warnings on imports of deprecated items. This bug, JDK-8032211, was fixed quite recently in our JDK 9 development line. In fact, we're still tuning up the handling of the @Deprecated annotation. For example, bug JDK-6481080 clarifies that attempting to use @Deprecated in a package-info.java file does not in fact deprecate the package; this bug was fixed just last week. And there is more work to be done but it's somewhat speculative at this point.

The JDK is facing similar problems to yours, in that we have to maintain deprecated APIs for clients that are still using them. But since we use and implement such APIs internally, we have a lot of deprecation warnings to suppress. As of this writing, in our JDK 9 development line, we still have not been able to compile the system without deprecation warnings. As a result, the javac options for lint warnings are still:

-Xlint:all,-deprecation

You will probably have to disable deprecation warnings in your compilation as well, especially if you are still building on JDK 6. I don't see a way around it at this point.

One final note on one of your deprecation cases:

@Deprecated
public class DeprecatedClass extends Bar<DeprecatedClass> { ... }

This does not issue a deprecation warning, nor should it. The Java Language Specification, section 9.6.4.6, specifies that deprecation warnings are not issued if the use of a deprecated entity is within an entity that is itself deprecated.

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.

Suppress Sonar's warning on import

Can you please try:

import com.sun.xml.ws.developer.JAXWSProperties; // NOSONAR 

How can I suppress javac warnings about deprecated api?

From what I can tell in the docs, you can't do it on the command-line.

According to the javac documentation, -Xlint:none only disables warnings "not mandated by the Java Language Specification". It appears that warning you of the use of deprecated APIs is managed by the language spec.

Your best option would be to fix the use of deprecated APIs. However, an option would be to add the @SuppressWarnings("deprecation") annotation to the classes or methods that are using the deprecated APIs.



Related Topics



Leave a reply



Submit