java warning: Varargs method could cause heap pollution from non-reifiable varargs parameter

前端 未结 5 1678
灰色年华
灰色年华 2021-01-17 17:32

I am using IntelliJ IDEA with javac on JDK 1.8. I have the following code:

class Test
{
    @SafeVarargs
    final void varargsMe         


        
5条回答
  •  萌比男神i
    2021-01-17 18:16

    None of the answers I've seen on this question seem to me to be satisfactory so I thought I'd take a stab at it.

    Here's the way I see it:

    1. @SafeVarargs

      • Is a cure for the warning: [unchecked] Possible heap pollution from parameterized vararg type Foo.
      • Is part of the method's contract, hence why the annotation has runtime retention.
      • Is a promise to the caller of the method that the method will not mess up the heap using the generic varargs argument.
    2. @SuppressWarnings("varargs")

      • Is a cure for the warning: [varargs] Varargs method could cause heap pollution from non-reifiable varargs parameter bar.
      • Is a cure for problems occurring within the method code, not on the method's contract, hence why the annotation only has source code retention.
      • Tells the compiler that it doesn't need to worry about a callee method called by the method code messing up the heap using the array resulting from the non-reifiable varargs parameter.

    So if I take the following simple variation on OP's original code:

    class Foo {
        static  void bar(final T... barArgs) {
            baz(barArgs);
        }
        static  void baz(final T[] bazArgs) { }
    }
    

    The output of $ javac -Xlint:all Foo.java using the Java 9.0.1 compiler is:

    Foo.java:2: warning: [unchecked] Possible heap pollution from parameterized vararg type T
        static  void bar(final T... barArgs) {
                                       ^
      where T is a type-variable:
        T extends Object declared in method bar(T...)
    1 warning
    

    I can make that warning go away by tagging bar() as @SafeVarargs. This both makes the warning go away and, by adding varargs safety to the method contract, makes sure that anyone who calls bar will not have to suppress any varargs warnings.

    However, it also makes the Java compiler look more carefully at the method code itself - I guess in order to verify the easy cases where bar() might be violating the contract I just made with @SafeVarargs. And it sees that bar() invokes baz() passing in barArgs and figures since baz() takes an Object[] due to type erasure, baz() could mess up the heap, thus causing bar() to do it transitively.

    So I need to also add @SuppressWarnings("varargs") to bar() to make that warning about bar()'s code go away.

提交回复
热议问题