Thursday, August 26, 2021

What is @SuppressWarnings annotation in Java? Unchecked, RawTypes, Serial Example

@SuppressWarnings annotation is one of the three built-in annotations available in JDK and added alongside @Override and @Deprecated in Java 1.5. @SuppressWarnings instruct the compiler to ignore or suppress, specified compiler warning in annotated element and all program elements inside that element. For example, if a class is annotated to suppress a particular warning, then a warning generated in a method inside that class will also be separated. You might have seen @SuppressWarnings("unchecked") and @SuppressWarnings("serial"), two of most popular examples of @SuppressWarnings annotation. Former is used to suppress warning generated due to unchecked casting while the later warning is used to remind about adding SerialVersionUID in a Serializable class.

Since @SuppressWarnings indicates potential programming error or mistake, it's recommended to use them sparingly and instead try to fix actual problem which is triggering that warning. Having said that, there are conditions, especially while using generics in Java, when you are absolutely sure that things won't go wrong, you can use @SuppressWarnings to suppress those warnings.

Also, worth following are advised  given by Josh Bloch in his famous book Effective Java, a must read for every Java programmer, to document reason for suppressing a warning as a comment.


List of @SuppressWarnings options on Java

Different compiler and IDEs support different list of @SuppressWarnings options. It seems IDE like Eclipse and Netbeans support more options than standard javac compiler.



You can get a list of supported @SuppressWarnings options for the Java compiler, by running the javac -X command. 

Here is a supported option for javac 1.6.0_26.
$ javac -version
  javac 1.6.0_26

$ javac -X
  -Xlint  Enable recommended warnings
  -Xlint:{all,cast,deprecation,divzero,empty,unchecked,
   fallthrough,path,serial,finally,overrides,-cast,
  -deprecation,-divzero,-empty,-unchecked,-fallthrough,
  -path,-serial,-finally,-overrides,none}Enable 
  or disable specific warnings

You can see supported values of @SuppressWarnings are :
  • all
  • cast
  • deprecation
  • divzero
  • empty
  • unchecked
  • fallthrough
  • path
  • serial
  • finally
  • overrides
You will see examples of a couple of these options, in our example of how to use @SuppressWarnings annotation in Java. To learn more about why you should suppress warnings, see Effective Java 3rd Edition by Joshua Bloch.

Unchecked @SuprressWarnings annotation in Java




How to @SuppressWarnings in Java?

In the last couple of paragraphs, we have seen what is @SuppressWarnings and list of @SuppressWarnings options supported by the javac compiler. Now we will see, when these warnings occur and how does it help to minimize potential errors?

If you are coding in Eclipse IDE, then you are likely to see many warnings as soon as you write code, which triggers any of these warnings. If you are compiling using javac, then you won't see all of these warnings, until you compile using -Xlint option.

javac -Xlint will show all warnings supported by javac compiler. One of the simplest examples is implementing a Serializable interface and forget to declare SerialVersionUID, which could break your application in the future if the structure of the class changes.

The Eclipse IDE will show a warning with underlined zigzag in yellow color. Now if you want to suppress that warning you can use @SuppressWarnings("serial") at your class level as shown below :

import java.io.Serializable;

@SuppressWarnings("serial")
public class Test implements Serializable{
    private String version;
    public String getVersion(){ return version };
}

Similarly, if you have used raw types i.e. Collections without generic, Eclipse will show you "rawtypes" warning as shown below :

public class RawType{
    public static void main(String args[]){
        @SuppressWarnings("rawtypes")
        List names = new ArrayList();
    }
}

here, we have used ArrayList as raw-type, and Eclipse is quick to point out that. Now, if you type Ctrl+1 which is Eclipse shortcut for show hint, it will give you the option to use @SuppressWarnings at main (method level) or at names (local variable level), always choose the lowest level, which is a local variable in this case. If you choose to put @SuppressWarnings("rawtypes") at the method level, Eclipse will suppress all raw-types warnings inside that method.

If we compile same code without @SuprressWarnings, using javac compiler it will show the following hint:

$ javac RawType.java
Note: RawType.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

and when you compile this code with java -Xlint, it will show detailed warnings:

$ javac -Xlint RawType.java
RawType.java:5: warning: [unchecked] unchecked conversion
found   : java.util.ArrayList
required: java.util.List
                List names = new ArrayList();

Similarly for an unused variable, Eclipse shows warnings, which can be suppressed by @SuppressWarnings(unused). Remember, by issuing these warnings, IDE and compiler help to find potential bugs at code time and compile time.

SuppressWarnings Annotation in Java Unchecked Rawtype Serial

Best Practices using @SuppressWarnings annotation in Java

Here are couple of things, which you can keep in mind while using @SuppressWarnings("") annotations:

1) Never put @SuppressWarnings("unchecked) or other options, at the class level, this would potentially mask critical warnings.


2) Use @SuppressWarnings at the smallest scope. Which means if the warning can be removed by putting @SuppressWarnings at a local variable then use that instead of annotating whole method. It's also worth knowing that suppress warnings annotation can be applied to class, field, method, parameter, constructor and local variables.


3) While using @SuppressWarnings("unchecked"), add a comment to explain about "why a particular portion of code is type-safe" before suppressing this warning. Every unchecked warning is an indication of potential ClassCastException at runtime, so don't ignore them.


4) Don't use @SuppressWarnings("all"), it will suppress all warnings, which can mask potential warnings which could lead to RuntimeException when you run the program.


That's all on what is @SuppressWarnings in Java, list of options supported by @SuppressWarnings and how to use them at class, method and field level. It's important to use them correctly, and you can choose to pay attention to some of them. At the same time, I don't suggest to suppress every warning shown by Eclipse, because it will clutter your code with lots of annotation, instead choose one's which really matters e.g. serial, uncheck or rawtypes.


No comments :

Post a Comment