Java @基于接口方法的SafeVarargs

Java @基于接口方法的SafeVarargs,java,generics,variadic-functions,Java,Generics,Variadic Functions,在这部法典中 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

在这部法典中

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
    }
}
package.com.example;
接口采集器{
//@SafeVarargs//错误:@SafeVarargs注释无法应用于非最终实例方法addAll
void addAll(T…值);
}
类收集器实现CollectorIF{
@安全变量
公共最终无效添加值(T…值){
}
}
类组件{
公共空间计算(T值){
收集器col1=新收集器();
col1.addAll(value);//无警告
CollectorIF col2=新收集器();
col2.addAll(value);//类型安全:为varargs参数创建一个T的泛型数组
}
}
类型安全性:由于
@SafeVarargs
注释,当使用
收集器
引用时,不会出现针对varargs参数创建的T的通用数组
警告

但是,当通过
CollectorIF
界面访问该方法时,会出现警告。在接口方法上,
@SafeVarargs
无效(这很明显,因为编译器无法对方法体中参数的使用情况执行任何检查)


通过接口访问方法时如何避免警告?

无法避免此警告,因为无法安全地定义具有泛型varargs方法的接口

CollectorIF
的另一个实现可能会误用该参数,使得
CollectorIF.addAll()
的任何调用方都容易受到奇怪的运行时行为的攻击。您可以假设接口和非final方法应该允许
@SafeVarargs
(并且要求实现/重写方法也要进行类似的注释),但目前Java开发人员有意识地决定不支持该模式

JLS提供了更多的背景信息:

当发生方法重写时,注释不可用。注释继承仅适用于类(而不是方法、接口或构造函数),因此@SafeVarargs样式的注释不能通过类中的实例方法或接口传递

同时,你有两个选择;忽略警告或重构API

重构您的API实际上可能正是您想要的,因为泛型vararg方法只应该用作真正的、正确的泛型实现的桥梁。与其将其定义为接口的一部分(因此要求所有实现都实现),不如将其作为静态实用程序方法提供,从而使接口的API更小,同时仍然为调用方提供使用varargs的灵活性。从Java8开始,实用程序方法甚至可以在接口中定义

@SafeVarargs
public static <T> void addAll(CollectorIF<T> collector, T... values) {
  collector.addAll(Arrays.asList(values));
}
@SafeVarargs
公共静态void addAll(CollectorIF collector,T…值){
collector.addAll(Arrays.asList(value));
}
然后,您的接口应该定义一个
addAll(Iterable values)
方法,让实现者完全避免泛型varargs的粗糙世界。

相关(无答案)