@SafeVarargs on interface method

泄露秘密 提交于 2019-12-08 15:09:39

问题


In this code,

package com.example;

interface CollectorIF<T> {
    // @SafeVarargs         // Error: @SafeVarargs annotation cannot be applied to non-final instance method addAll
    void addAll(T... values);   
}

class Collector<T> implements CollectorIF<T> {

    @SafeVarargs
    public final void addAll(T... values) {
    }
}

class Component<T> {

    public void compute(T value) {
        Collector<T> col1 = new Collector<>();
        col1.addAll(value);   // No warning

        CollectorIF<T> col2 = new Collector<>();
        col2.addAll(value);   // Type safety: A generic array of T is created for a varargs parameter
    }
}

the Type safety: A generic array of T is created for a varargs parameter warning does not occur when using a Collector<T> reference, due to the @SafeVarargs annotation.

However, the warning does occur when accessing the method through the CollectorIF<T> interface. On interface methods, @SafeVarargs is not valid (which is obvious since the compiler can not perform any checks on the usage of the parameter in the method body).

How can the warning be avoided when accessing the method through an interface?


回答1:


There's no way to avoid this warning, because there's no way to safely define an interface that has a generic varargs method.

Another implementation of CollectiorIF could misuse the parameter, rendering any caller of CollectorIF.addAll() vulnerable to strange runtime behavior. You could make a case that interfaces and non-final methods should allow @SafeVarargs (and require that implementing/overriding methods be similarly annotated), but presently the Java devs made a conscious decision not to support that pattern.

The JLS provides a little more background:

The annotation is not usable where method overriding occurs. Annotation inheritance only works on classes (not methods, interfaces, or constructors), so an @SafeVarargs-style annotation cannot be passed through instance methods in classes or through interfaces.

~JLS §9.6.4.7

In the meantime you have two choices; ignore the warning or refactor your API.

Refactoring your API is actually likely to be exactly what you want, since generic vararg methods should only be used as bridges to the real, properly-generic implementation. Instead of defining it as part of your interface (and therefore requiring all implementations implement it) provide it as a static utility method, thereby making the interface's API smaller while still giving callers the flexibility to use varargs. As of Java 8 the utility method can even be defined in the interface.

@SafeVarargs
public static <T> void addAll(CollectorIF<T> collector, T... values) {
  collector.addAll(Arrays.asList(values));
}

Your interface should then define a addAll(Iterable<T> values) method which lets implementors avoid the crufty world of generic varargs entirely.



来源:https://stackoverflow.com/questions/37829160/safevarargs-on-interface-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!