12

Ok so I'm calling a method with a signature (Class<? extends Throwable>... exceptions) and I get a "File.java uses unchecked or unsafe operations" warning here in the main method:

public class VarargsFun {
    public void onException(Class<? extends Throwable>... exceptions) { }

    public static void main(String[] args) {
        new VarargsFun().onException(IllegalArgumentException.class);
    }
}

Shouldn't the compiler be able to see that IllegalArgumentException does indeed extend RuntimeException, Exception and Throwable?

How should I properly amend my code to get rid of this warning?

I don't really feel like instantiating my exceptions... it seems nicer to use the .class

(dont want to use @SuppressWarnings either!)

Am using java 7. Thanks for any tips.

Mark Peters
  • 76,122
  • 14
  • 153
  • 186
vikingsteve
  • 34,284
  • 19
  • 101
  • 142

2 Answers2

13

Because varargs are actually just arrays, and generics and arrays don't mix (well), Java has traditionally given a warning when you call a method with a generic vararg type. This is because the array is technically being created at the caller.

However, it soon became evident that arrays created solely to be passed to a varargs method did not suffer from the same danger as normal generic arrays from the caller's perspective, however the method itself that received the generic array could abuse them. So in Java 7 forward, the warning appears on the method itself (in your case, onException) and can be suppressed by using the @SafeVarargs annotation on the method:

@SafeVarargs
public void onException(Class<? extends Throwable>... exceptions) { }

If you're not in fact using the Java 7 language, or if you can't change onException (presumably because it's a library method) then you can safely use @SuppressWarnings to hide that warning:

@SuppressWarnings("unchecked")
public static void main(String[] args) {
    new VarargsFun().onException(IllegalArgumentException.class);
}

If you suppress warnings in this way however, take care to isolate this one statement in its own method so that you don't accidentally suppress other future warnings.

Personally, I disable generic vararg warnings completely in my IDE, because they almost never indicate incorrect code from the point of view of the caller.

Community
  • 1
  • 1
Mark Peters
  • 76,122
  • 14
  • 153
  • 186
12

It's easiest to understand if you realize that

new VarargsFun().onException(IllegalArgumentException.class);

is just syntactic sugar for

new VarargsFun().onException(
    new Class<? extends Throwable>[]{ IllegalArgumentException.class });

i.e. the call site creates an array with the component type equal to the type of the varargs.

But of course, new Class<? extends Throwable>[] is not allowed in Java. So the compiler does new Class<?>[] instead and gives a warning.

newacct
  • 110,405
  • 27
  • 152
  • 217