代码之家  ›  专栏  ›  技术社区  ›  ayushgp

在方法接受类中使用enum的接口方法

  •  15
  • ayushgp  · 技术社区  · 8 年前

    我有一个需要接受枚举类的方法。这些枚举实现一个接口。现在,我需要访问枚举方法(如ordinal()、name()等)和接口方法。我所尝试的:

    public <T extends ConfigFeature, Enum> void showEnabledFeatures(Class<T> enumType, long mask) {
        List<T> list = Arrays.asList(enumType.getEnumConstants());
        list.forEach(item -> {
            // My interface's method, works fine
            item.getMask();
            // Enum method doesn't work:
            // item.ordinal();
        });
    }
    

    颠倒顺序会颠倒工作:

    public <T extends Enum, ConfigFeature> void showEnabledFeatures(Class<T> enumType, long mask) {
        List<T> list = Arrays.asList(enumType.getEnumConstants());
        list.forEach(item -> {
            // My interface's method, doesn't work now
            // item.getMask();
            // Enum method now works:
            item.ordinal();
        });
    }
    

    有没有办法从接口和枚举访问这两个方法?

    4 回复  |  直到 8 年前
        1
  •  23
  •   Salem    8 年前

    你用的语法不对 T 必须实现此接口,并且是枚举。

    这是:

    <T extends ConfigFeature, Enum>
    

    不受约束 T Enum ,但实际上创建了一个名为 枚举

    同样地,

    <T extends Enum, ConfigFeature>
    

    不受约束 T ConfigFeature 。您正在声明一个名为 配置功能

    正确的语法是使用 & :

    <T extends Enum<T> & ConfigFeature>
    

    请注意,这里的顺序实际上很重要! 枚举 只能排在第一位。

    根据 here ,只有第一个约束可以是类,之后的约束必须都是接口:

    TypeParameter:
        {TypeParameterModifier} Identifier [TypeBound]
    
    TypeParameterModifier:
        Annotation
    
    TypeBound:
        extends TypeVariable
        extends ClassOrInterfaceType {AdditionalBound}
    
    AdditionalBound:
        & InterfaceType
    
        2
  •  14
  •   Erwin Bolwidt    8 年前

    您的语法错误;您需要:

    public <T extends Enum<T> & ConfigFeature>
    

    您使用的语法创建了两个泛型类型参数,其中一个称为 T 还有一个叫 Enum (其中 枚举 不有界且t有界延伸 ConfigFeature )。

    注意,为了避免任何关于使用原始类型的泛型警告,还必须向 枚举 跳跃调用的枚举 X 始终扩展 Enum<X> ,因此您可以使用 T extends Enum<T> ,方法本地泛型声明的全文变为 <T extends Enum<T> & ConfigFeature>

        3
  •  6
  •   a_horse_with_no_name    8 年前

    更换 , 在第二个示例中 & 。您可以使用 & 声明多个边界,只要它们是从第二种类型开始的接口。如果使用逗号,则它是一个单独的类型参数,而不是一个绑定。

        4
  •  1
  •   Piro    8 年前

    只是为了添加现有答案,而不是使用 Mutliple Bounds 如其他答案中所述,您可以定义将所需接口与枚举的返回方法相结合的接口,如:

    public interface ConfigFeatureEnumI <T extends Enum<T>> extends ConfigFeatureI{
        @SuppressWarnings("unchecked")
        default public T asEnum() {
            return (T) this;
        }
    }
    

    您可以实现 asEnum() 在使用的枚举中,或者如果Java 8可用,则只使用默认方法,如我在这里所示。

    public enum ConfigEnum implements ConfigFeatureEnumI<ConfigEnum>{//...
    

    然后 showEnabledFeatures 可能看起来像:

    public <T extends ConfigFeatureEnumI<?>> void showEnabledFeatures(Class<T> enumType, long mask) {
        List<T> list = Arrays.asList(enumType.getEnumConstants());
        list.forEach(item -> {
            // Interface method works:
            item.getMask();
            // Enum method works via asEnum():
            item.asEnum().ordinal();
        });
    }
    

    虽然添加新接口并不理想,但对于不太了解Java泛型或从未使用过多个边界(我经常使用泛型,但从来都不需要这样的功能,所以当我看到它时,我有点不习惯)的程序员来说,使用它会更容易。