EnumSet 作为泛型接口中的参数

Vat*_*ash 0 java generics inheritance enums enumset

我有一个用例:

inteface A{
  get(EnumSet<?> fetchModes);
}
class B implements A{

  //Here FetchMode is an enum
  get(EnumSet<FetchMode> fetchMode){
   //Some logic here
  }
}
Run Code Online (Sandbox Code Playgroud)

但它抛出编译时错误:

类 B 的方法 get 与类型 A 的 get(EnumSet fetchMode) 具有相同的擦除,但不会覆盖它。

我读过 Enums 不能是通用的,但是有什么方法可以实现这个用例吗?(基本上希望 EnumSet 是通用的,不同的实现可以传递不同的 Enum)

Rav*_*ala 5

如果参数类型完全匹配,则方法可以覆盖另一个方法,但您的方法不匹配。尽管EnumSet<FetchMode>是 的子类型EnumSet<?>,但它们并不完全相同。您不是get(EnumSet<?> fetchModes);在子类中覆盖超类方法,而是使用不同的参数类型重载它。由于在检查或反编译字节码时被擦除,这两个具有相同的签名,get(EnumSet fetchModes)并且编译器开始抱怨。

这在 JLS §8.4.8.1 中有介绍

一个类不能有两个具有相同名称和类型擦除的成员方法

解决该问题的天真尝试是更改参数类型,使其与超类的参数类型兼容,并在您的子类中正确覆盖该方法。

@Override
public void get(EnumSet<?> fetchModes) {

}
Run Code Online (Sandbox Code Playgroud)

尽管这在某种程度上修复了编译器错误,但它仍然不优雅,因为它允许您的 EnumSet 存储任何对象。但理想情况下,您可能希望它仅存储 Enum 的某些子类型。这个习语支持这一点。

您需要做的是声明一个具有有界类型参数的泛型接口,然后通过正确覆盖该方法来实现它,如下所示。

public interface A<E extends Enum<E>> {
    void get(EnumSet<E> fetchModes);
}

public class B implements A<FetchMode> {
    @Override
    public void get(EnumSet<FetchMode> fetchModes) {

    }
}
Run Code Online (Sandbox Code Playgroud)