@SafeVarargs 接口方法
@SafeVarargs on interface method
在此代码中,
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
}
}
由于 @SafeVarargs
注释,使用 Collector<T>
引用时不会出现 Type safety: A generic array of T is created for a varargs parameter
警告。
但是,通过CollectorIF<T>
接口访问该方法时,警告确实发生。在接口方法上,@SafeVarargs
无效(这是显而易见的,因为编译器无法对方法主体中参数的使用执行任何检查)。
通过接口访问方法时如何避免warning?
无法避免此警告,因为无法安全地定义具有通用可变参数方法的接口。
CollectiorIF
的另一个实现可能会滥用该参数,从而使 CollectorIF.addAll()
的任何调用者容易受到奇怪的运行时行为的影响。您可以假设接口和非最终方法 应该 允许 @SafeVarargs
(并要求 implementing/overriding 方法进行类似注释),但目前 Java 开发人员有意识地决定不支持该模式。
JLS 提供了更多背景信息:
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.
同时你有两个选择;忽略警告或重构你的 API.
重构您的 API 实际上可能正是您想要的,因为通用可变参数方法只应用作通向真正的、适当通用实现的桥梁。与其将其定义为接口的一部分(因此要求所有实现都实现它),不如将其作为静态实用方法提供,从而使接口的 API 更小,同时仍然为调用者提供使用可变参数的灵活性。从 Java 8 开始,实用方法甚至可以在接口中定义。
@SafeVarargs
public static <T> void addAll(CollectorIF<T> collector, T... values) {
collector.addAll(Arrays.asList(values));
}
然后您的接口应该定义一个 addAll(Iterable<T> values)
方法,让实现者完全避免通用可变参数的繁琐世界。
在此代码中,
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
}
}
由于 @SafeVarargs
注释,使用 Collector<T>
引用时不会出现 Type safety: A generic array of T is created for a varargs parameter
警告。
但是,通过CollectorIF<T>
接口访问该方法时,警告确实发生。在接口方法上,@SafeVarargs
无效(这是显而易见的,因为编译器无法对方法主体中参数的使用执行任何检查)。
通过接口访问方法时如何避免warning?
无法避免此警告,因为无法安全地定义具有通用可变参数方法的接口。
CollectiorIF
的另一个实现可能会滥用该参数,从而使 CollectorIF.addAll()
的任何调用者容易受到奇怪的运行时行为的影响。您可以假设接口和非最终方法 应该 允许 @SafeVarargs
(并要求 implementing/overriding 方法进行类似注释),但目前 Java 开发人员有意识地决定不支持该模式。
JLS 提供了更多背景信息:
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.
同时你有两个选择;忽略警告或重构你的 API.
重构您的 API 实际上可能正是您想要的,因为通用可变参数方法只应用作通向真正的、适当通用实现的桥梁。与其将其定义为接口的一部分(因此要求所有实现都实现它),不如将其作为静态实用方法提供,从而使接口的 API 更小,同时仍然为调用者提供使用可变参数的灵活性。从 Java 8 开始,实用方法甚至可以在接口中定义。
@SafeVarargs
public static <T> void addAll(CollectorIF<T> collector, T... values) {
collector.addAll(Arrays.asList(values));
}
然后您的接口应该定义一个 addAll(Iterable<T> values)
方法,让实现者完全避免通用可变参数的繁琐世界。