我有一个需要接受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访问这两种方法?
答案 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泛型的程序员来说可能更容易使用(我经常使用泛型,但从不需要这样的功能,所以我有点当我确实看到它的时候。)