在接受类的方法中使用枚举的接口方法

时间:2018-03-09 07:00:12

标签: java enums

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

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();
    });
}

有没有办法从界面和Enum访问这两种方法?

4 个答案:

答案 0 :(得分:23)

您使用错误的语法表示T必须实现此接口并且是枚举。

此:

<T extends ConfigFeature, Enum>

并未将T限制为Enum,而是实际创建名为Enum的新通用参数。

类似地,

<T extends Enum, ConfigFeature>

不会将T限制为ConfigFeature。您正在声明一个名为ConfigFeature的新通用参数。

正确的语法是使用&

<T extends Enum<T> & ConfigFeature>

请注意,订单在这里非常重要! Enum只能先出现。

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

TypeParameter:
    {TypeParameterModifier} Identifier [TypeBound]

TypeParameterModifier:
    Annotation

TypeBound:
    extends TypeVariable
    extends ClassOrInterfaceType {AdditionalBound}

AdditionalBound:
    & InterfaceType

答案 1 :(得分:14)

你的语法错了;你需要:

public <T extends Enum<T> & ConfigFeature>

您使用的语法创建了两个通用类型参数,一个名为T,另一个名为Enum(其中Enum没有限制,T限制为{{1} }})。

请注意,为了避免关于使用原始类型的任何泛型警告,您还必须为ConfigFeature边界提供类型参数。名为Enum的枚举始终展开X,因此您可以使用Enum<X>,方法本地通用声明的全文变为T extends Enum<T>

答案 2 :(得分:6)

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

答案 3 :(得分:1)

只是添加到现有答案,而不是像其他答案中所述使用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泛型的程序员来说可能更容易使用(我经常使用泛型,但从不需要这样的功能,所以我有点当我确实看到它的时候。)

相关问题