【问题标题】:Accessing parent methods of generic enum which implements interface访问实现接口的通用枚举的父方法
【发布时间】:2014-06-30 03:29:36
【问题描述】:

好的,我目前正在定义通用枚举参数,如下所示:

public interface MyInterface
{
    public int GetValue ( );
}

public enum MyEnum implements MyInterface
{
    value1(1), value2(2);

    int myvalue;

    MyEnum ( int value )
    {
        this.myvalue = value;
    }

    public int GetValue ( )
    {
        return this.myvalue;
    }
}

public class PassGeneric
{
    public void AcceptsGeneric ( Enum<? extends MyInterface> generic_enum )
    {
        generic_enum.values();                                 // Not valid
        generic_enum.GetValue();                               // Not valid
        generic_enum.getDeclaringClass().getEnumConstants();   // Valid
        ((Enum<?>)generic_enum).values();                      // Not Valid
        ((MyInterface)generic_enum).GetValue();                // Valid
    }
}

我只是想了解为什么类型说明符 Enum&lt;? extends MyInterface&gt; 不允许我 1) 直接访问 MyInterface 方法,以及 2) 直接访问 Enum 方法,例如 .values()

强制转换适用于访问MyInterface 方法,但对我来说,指定泛型类型扩展MyInterface 的目的是失败的,因为将Enum&lt;? extends MyInterface&gt; 替换为Enum&lt;?&gt; 并将对象强制转换为@987654329 仍然是合法的@。

如果我误解了泛型的使用和实现extends,有人可以向我解释如何正确地明确指定泛型实现给定接口。

【问题讨论】:

  • 你有什么理由只使用MyInterface作为参数吗?
  • 因为我也想访问.values()等枚举方法

标签: java generics interface enums


【解决方案1】:

您无法访问values(),因为它不是实例方法;它是属于枚举类型的静态方法。因此,传递超类 Enum 的实例不会为您提供所需的信息。

就接口方法而言,声明Enum&lt;? extends MyInterface&gt; 声明了有关枚举 的某些通用信息,但并没有告诉编译器generic_enum 本身就是MyInterface 的一个实例。

如果你想声明 generic_enum 实现 MyInterface,你应该这样做:

public void AcceptsGeneric ( MyInterface generic_enum )

如果出于某种原因,您需要知道它实现了MyInterface 并且它是一个枚举,您可以按如下方式声明您的方法:

public <T extends Enum<T> & MyInterface> void AcceptsGeneric ( T generic_enum )

【讨论】:

  • Enum上不应该有泛型参数吗?
【解决方案2】:

将方法的参数声明为Enum&lt;? extends MyInterface&gt; generic_enum 限制了generic_enum 的方法,您无需强制转换即可访问Enum 的方法。 type 参数不会将类型更改为 Enum 以外的其他类型。因此这些行无效:

generic_enum.values();
generic_enum.GetValue();
((Enum<?>)generic_enum).values(); // ((Enum<?>)generic_enum) still of type Enum

现在让我们看看下面一行:

((MyInterface)generic_enum).GetValue();

没有理由不允许演员。扩展Enum 的类可以实现MyInterface。因此,没有理由禁止该演员表。 (编译器不会禁止这样做,只是因为 ClassCastException 可能在运行时发生)。

现在剩下的一行:

generic_enum.getDeclaringClass().getEnumConstants();

因为generic_enumEnum&lt;? extends MyInterface&gt; 类型,所以generic_enum.getDeclaringClass() 的返回类型是Class&lt;? extends MyInterface&gt;。由于Class 包含一个方法getEnumConstants(),因此该行是有效的。

由于您仍然可以访问 generic_enum 类中的值,因此您可以将 AcceptsGeneric 声明为

public void AcceptsGeneric(MyInterface generic_enum)

public<T extends Enum<T> & MyInterface> void AcceptsGeneric(T generic_enum)

并使用

generic_enum.getClass().getEnumConstants()

获取值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-11
    • 2020-11-28
    相关资源
    最近更新 更多