具有有限枚举参数边界的通用方法-无法访问values()方法

5

我想编写一个通用的方法,接受一个绑定了范围的参数,该参数扩展自Enum。举个例子,如果有以下枚举:

public enum InputFlags{
    ONE (0000001),
    TWO (0000002),
    THREE (00000004);

    public final int value;

    InputFlags(int value){
        this.value = value;
    }
}

我可以接下来做以下事情:
for (InputFlags ifg : InputFlags.values()){
            // Do something with ifg
}

然而,如果我尝试使用一个具有边界返回参数的通用方法来执行上述操作,我将无法访问values()方法:
public static <T extends Enum> T getFlags(int f){
        T.values(); // NOT allowed, even though I have bounded by extending Enum.
}

看起来我无法在通用方法中访问values()。这是枚举的特殊性还是有其他解决方法?


看起来你正在重新发明 EnumSet - Holger
3个回答

9

values()在Java中是一件非常奇怪的事情。查看Enum文档 - values()甚至都不在那里!实际上,values()根本不是Enum的方法。相反,对于每个扩展Enum的类,都会隐式添加一个名为values()static方法。但是,一个enumvalues()方法与另一个enum中的values()方法是不同的。

T extends Enum意味着如果t具有类型T,则可以在t上调用来自Enum实例方法。您无法调用Enumstatic方法(即使您可以,values()也不存在!)

values()仅在您知道实际的enum名称时有用。当您只拥有类型参数T时,它无法使用。

解决这个问题的方法是传递一个Class对象。像这样:

public static <T extends Enum<T>> T getFlags(Class<T> clazz, int f){
    T[] array = clazz.getEnumConstants();  // This is how you can get an array.
    Set<T> set = EnumSet.allOf(clazz);     // This is how you can get a Set.     
}

1

values()是编译器在InputFlags类中插入的静态方法。因此,不可能使用T.values(),特别是因为T是一个泛型类型。但是,如果您可以获取T的Class对象(通常通过getClass()或将其传递给getFlags(int f, Class<T> clazz)),则可以在该对象上使用Class#getEnumConstants()


我仍然无法理解为什么它不可用,因为我已将参数限定为“枚举”。我想我需要再思考一段时间。 - D-Dᴙum
values() 是 Enum 的每个子类中的静态方法,但不是 Enum 本身的方法。因此,编译器无法将该方法视为 Enum 的成员。此外,静态方法的位置(即它所属的类)在编译时解析,这里无法完成。 - Clashsoft

0

这是static方法的一个特殊性质。在Java中,无论是使用泛型还是其他方式,都没有办法定义适用于static方法的接口,即类应该/必须实现static方法。

此外,类型擦除(以及其他因素)防止您在static方法调用表达式中使用类型变量T作为类型名称。


如果我去掉static关键字,问题仍然存在。 - D-Dᴙum
@kerry,“values”是“静态”方法,而不是你的“getFlags”。 - Sotirios Delimanolis
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - D-Dᴙum
@Kerry 实例方法是在引用值上调用的,而不是静态方法。 - Sotirios Delimanolis
@Kerry 注意,这与枚举类型无关。它适用于每个引用类型。 - Sotirios Delimanolis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接