【问题标题】:Generic Method With Bounded Extends Enum Parameter - Cannot Access values() method有界扩展枚举参数的通用方法 - 无法访问 values() 方法
【发布时间】:2015-01-12 07:11:36
【问题描述】:

我想编写一个泛型方法,它采用扩展 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()。这是枚举的特性还是有办法解决这个问题?

【问题讨论】:

标签: java generics enums


【解决方案1】:

values() 在 Java 中是一个很奇怪的东西。在文档中查找 Enum - values() 甚至不存在! values() 根本不是 Enum 的方法。相反,一个名为values()static 方法被隐式添加到每个扩展Enum 的类中。但是一个enumvalues() 方法与另一个enumvalues() 方法不同。

T extends Enum 这一事实意味着如果t 的类型为T,您可以在t 上从Enum 调用instance 方法。你不能调用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.     
}

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我仍然无法理解为什么它不可用,因为我已将参数限制为Enum。我想我需要考虑一段时间..
    • values() 是 Enum 的每个子类中的静态方法,但不是 Enum 本身的方法。因此,编译器找不到作为 Enum 成员的方法。此外,静态方法的位置(即它所属的类)是在编译时解析的,这在此处无法完成。
    【解决方案3】:

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

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

    【讨论】:

    • 如果我去掉 static 关键字,我仍然会遇到同样的问题。
    • @kerry valuesstatic 方法,而不是您的 getFlags
    • 好的,我误解了您对 static 关键字的理解。我需要考虑您的答案,因为我无法自己解决这个问题。在我的(简单)视图中,由于我已将泛型方法中的参数限制为枚举,那么肯定所有枚举方法(静态或非静态)都应该可用。
    • @Kerry 实例方法,在参考值上调用,当然。不是静态方法。
    • @Kerry 请注意,这与枚举类型无关。它适用于所有引用类型。
    猜你喜欢
    • 2010-09-21
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    • 1970-01-01
    • 2012-01-10
    相关资源
    最近更新 更多