@SafeVarargs接口方法 [英] @SafeVarargs on interface method

查看:138
本文介绍了@SafeVarargs接口方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这段代码中,

  package com.example; 

interface CollectorIF< T> {
// @SafeVarargs //错误:@SafeVarargs注解不能应用于非final实例方法addAll
void addAll(T ... values);
}

class Collector< T>实施CollectorIF< T> {

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

class Component< T> {

public void compute(T value){
收集器< T> col1 =新收集器<>();
col1.addAll(value); //无警告

CollectorIF< T> col2 =新收集器<>();
col2.addAll(value); //类型安全性:为可变参数
}
}


$ b创建一个T的通用数组$ b

类型安全性:使用收集器< t>时,不会出现警告参数的可变参数的通用数组 引用,因为 @SafeVarargs 注释。 然而,警告 在通过 CollectorIF< T> 界面访问方法时发生。在接口方法中, @SafeVarargs 无效(这很明显,因为编译器无法对方法体中参数的使用进行任何检查)。



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

解决方案

无法避免此警告,因为无法安全定义具有通用可变参数方法的接口。



另一个 CollectiorIF 可能会误用该参数,导致 CollectorIF.addAll()的任何调用者容易受到奇怪的运行时行为的影响。你可以提出一个例子,接口和非final方法应该允许 @SafeVarargs (并且要求实现/覆盖方法被类似地注释),但是目前Java开发人员有意识地决定不支持该模式。



JLS提供了更多的背景:

< blockquote>

注释在发生方法覆盖时不可用。注释继承仅适用于类(不是方法,接口或构造函数),所以@ SafeVarargs风格的注释不能通过类或接口中的实例方法传递。



〜JLS§9.6.4.7

与此同时,您有两种选择;忽略警告或重构您的API。

重构您的API实际上可能正是您想要的,因为泛型可变参数方法应该仅用作实际的桥梁,适当的通用实现。与其将其定义为接口的一部分(因此要求所有实现实现它)将其作为静态实用程序方法提供,从而使接口的API更小,同时仍使呼叫者能够灵活地使用可变参数。从Java 8开始,实用方法甚至可以在界面中定义。

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

然后,您的界面应该定义一个 addAll(Iterable< T>值)方法,它允许实现者完全避免通用可变参数的垃圾世界。


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?

解决方案

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.

这篇关于@SafeVarargs接口方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆