Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the placement of @SuppressWarnings("unchecked") matter?

Tags:

java

unchecked

I had used @SuppressWarnings("unchecked") like:

class SomeClass {
  public static void main(String [] args) {
    Vector v = new Vector();
    @SuppressWarnings("unchecked")
    v.addElement(new Integer(1_000_000));
    // ...        

On compilation using javac version 8.0, I got the following errors:

error: <identifier> expected
        v.addElement(new Integer(1_000_000));

with the caret (^) pointing at the opening bracket of addElement method and one more error message complaining missing semicolon(;). The second message showed the caret near the closing bracket of addElement.

However, when I moved the @SuppressWarnings("unchecked") above the class SomeClass{, line, as in:

@SuppressWarnings("unchecked")
class SomeClass {

both the error messages disappeared automagically. This baffled me to any end. Is the positioning of @SuppressWarnings("unchecked") so critical?

like image 528
Seshadri R Avatar asked Sep 07 '16 09:09

Seshadri R


2 Answers

You must not place annotations like @SuppressWarnings("unchecked") on a statement but only on a declaration.

That's why the compiler does not understand the first variant:

@SuppressWarnings("unchecked")
v.addElement(new Integer(1_000_000));

It's just illegal there and the compiler won't understand it.

You could put it on the method instead, if you want to reduce the scope:

@SuppressWarnings("unchecked")
public static void main(String [] args) {
    Vector v = new Vector();
    v.addElement(new Integer(1_000_000));

Thus, only warnings for the main method will be ignored, but not for the whole class.

You can even put it on the variable declaration, but never on a statement:

@SuppressWarnings("unchecked")
Vector v = new Vector();

However, as GhostCat has pointed out, in this case it is probably better to just generify the vector instead of ignoring warnings.

like image 132
Michaela Maura Elschner Avatar answered Nov 10 '22 00:11

Michaela Maura Elschner


One could say: you can't place this annotation on statements, such as v.add(1); instead it should go on a declaration, but that answer would leave out to many important aspects here.

Thing is: you can use annotations to prevent the compiler giving you warnings on the one hand. On the other hand, you only want to suppress those warnings that you understand, and that you consider "ok to be suppressed".

Coming from that point of view, you always to annotate on the "smallest" level possible. Thus, the annotation would go here:

@SuppressWarnings("unchecked")
Vector v = new Vector();

But of course, in your case the warning is absolutely valid; and suppressing it is wrong.

Just change your code to:

Vector<Integer> v = new Vector<>();

and voilà no more need for the annotation at all.

In other words: you work your way from "in to out". Meaning: if you need to suppress warnings, you first go for the individual variables that give you the warning. And only if you got too many such statements in one method, you put the annotation on the method. You never ever want to annotate the whole class. Because that would suppress all such warnings in the whole class.

And honestly: the real lesson learned here: study the concepts you are using. The compiler is giving you a warning because you are using a raw type (by omitting the type parameter when declaring v). Then ignoring that warning is wrong wrong wrong. You figure what the warning is telling you, and then you fix your code instead!

"Good code" is completely warning free; and it has as few "suppress" annotations as possible!

like image 41
GhostCat Avatar answered Nov 10 '22 00:11

GhostCat