根据输入的Enum值返回强制转换的对象

Mit*_*dge 5 java generics enums casting

我试图制作一个采用Enum值并返回基于该Enum值强制转换为类的对象的方法。例如,我有一个名为ComponentType的枚举:

public enum ComponentType
{
    HEALTH(HealthComponent.class),
    HUNGER(HungerComponent.class);

    private Class<? extends Component> componentClass;

    private ComponentType(Class<? extends Component> componentClass)
    {
        this.componentClass = componentClass;
    }

    public Class<? extends Component> getComponentClass()
    {
        return componentClass;
    }
}
Run Code Online (Sandbox Code Playgroud)

“ HealthComponent”和“ HungerComponent”是两个类,它们都扩展了称为“ Component”的类。对于这个问题,它们内部的内容并不重要。

一个实体将具有为其分配的组件的列表(例如,一个实体可能有饥饿感,而另一个实体可能有健康状况,而另一个实体可能同时有健康状况)。

我的目标是在Entity内部创建一个方法,当传入ComponentType Enum中的值时,将返回转换为该值的对应类类型的Component对象。因此,如果传入ComponentType.HEALTH,则该方法将返回强制转换为HealthComponent的对象。这是我正在尝试的方法,但是不起作用:(编辑:请参见下文)

public <T extends Component> T getComponentByType(ComponentType type)
{
    Class<? extends Component> componentClass = type.getComponentClass();
    for(Component component : componentList)
    {
        if(component.getClass() == componentClass)
        {
            return (T) componentClass.cast(component);
        }
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

对于上述方法,当传入ComponentType.HEALTH类型时:

entity.getComponentByType(ComponentType.HEALTH);
Run Code Online (Sandbox Code Playgroud)

将转换为强制转换为“ Component”而不是“ HealthComponent”的对象。我希望它返回转换为HealthComponent而不是Component的对象。

有什么办法吗?我觉得这应该是可能的。我尝试找到一种方法来执行此操作的原因是因为它看起来像在进行所有以下铸造:

HealthComponent component = (HealthComponent) entity.getComponentByType(ComponentType.HEALTH);
Run Code Online (Sandbox Code Playgroud)

有点浪费,因为该方法可以(希望)假设我想要通过传入的ComponentType强制转换为什么。

编辑(更多信息):

仔细观察结果,我注意到我的方法在某种程度上可行。我的意思是,如果我输入以下内容,那么在Eclipse中:

component = entity.getComponentByType(ComponentType.HEALTH);
Run Code Online (Sandbox Code Playgroud)

(尚未定义component变量),然后将鼠标悬停在getComponentByType上以查看其返回的内容,并表示正在返回 <Component> Component

但是,如果我手动定义变量类型(大多数情况下,我只是让Eclipse为我创建变量),如下所示:

HealthComponent component = entity.getComponentByType(ComponentType.HEALTH);
Run Code Online (Sandbox Code Playgroud)

然后将鼠标悬停在getComponentByType上以查看其返回的内容,并说它正在返回<HealthComponent> HealthComponent,并且确实可以编译并运行。因此,从技术上讲,它是可行的,但并不是我想要的那样。这是一个小问题,因为如果我在第一个示例中告诉Eclipse为我创建一个局部变量,它将创建一个类型为“ Component”的变量,而我必须手动更改它。

Med*_*o42 2

您希望 的编译时返回类型getComponentByType()取决于用于选择组件的参数。这对于泛型来说是可能的,但前提是参数实际上携带了您需要的编译时类型信息。

不幸的是,您无法将类型参数添加到枚举值(请参阅此问题),但是如果您再次查看自己的代码,您可能会意识到您已经有一个对象可以恰当地描述您想要获取的组件,并且这种情况发生了携带我们需要的类型信息:Class<>每个组件类型的对象!

所以,这是我对你的函数的建议(未编译或测试,请注意,我的 Java 可能生锈了):

public <T extends Component> T getComponentByType(Class<T> type)
{
    for(Component component : componentList)
    {
        if(component.getClass() == type)
        {
            return (T)component;
        }
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)