简体   繁体   English

Java泛型-将一个泛型转换为另一个

[英]Java generics - casting one generic to another

Here's my code: 这是我的代码:

public class AnimationManager<STATE> {


private Map<STATE, Animation> animationMap = new HashMap<STATE, Animation>();


public void addAnimation(STATE state, BufferedImage[] frames, int frameDuration){
        animationMap.put(state, new Animation(frames, frameDuration));
}

public <E extends Enum<E>> void initAnimations(Player player, Constants.Heros chosen_hero, Class<E> heroStates){
        LinkedList<BufferedImage[]> frames = AssetsManager.getHeroGraphics(chosen_hero);

        assert frames != null;

        player.width = frames.get(0)[0].getWidth();
        player.height = frames.get(0)[0].getHeight();

        for(int i=0;i<frames.size();i++)
            addAnimation(heroStates.getEnumConstants()[i],frames.get(0),15);

}

}

At this line: 在这一行:

addAnimation(heroStates.getEnumConstants()[i],frames.get(0),15);

compiler shouts: Wrong 1st argument type, found 'E', required 'STATE'. 编译器大喊: 错误的第一个参数类型,找到“ E”,需要“ STATE”。

When initAnimations() method is in a different class (without STATE) it compiles and works like a charm. initAnimations()方法位于不同的类中(没有STATE)时,它将编译并像initAnimations()一样工作。 How is that possible that he doesn't want to get the first parameter and convert it to a STATE type? 他怎么可能不想获取第一个参数并将其转换为STATE类型?

The type parameter STATE are unbounded and can be invoked with any class. 类型参数STATE是不受限制的,可以与任何类一起调用。 The type parameter E is bounded to be a subclass of Enum. 类型参数E必然是Enum的子类。 The variable heroStates are a Class which means the getEnumConstants() method returns an array of E (which means an array of some subclass of Enum). 变量heroStates是一个Class,这意味着getEnumConstants()方法返回E数组(这意味着Enum的某些子类的数组)。 That can not safely be cast to the type of STATE. 无法安全地将其强制转换为STATE类型。

There are several ways to proceed from here, depending on your specific requirements. 根据您的特定要求,有几种方法可以从这里进行。 If casting can be avoided, that would be preferable. 如果可以避免铸造,那将是更好的选择。

If you know that STATE type parameter always is going to be an enum, you could put a bound on STATE and skip the type parameter E altogether: 如果您知道STATE类型参数始终将是一个枚举,则可以对STATE设置一个界限,并完全跳过类型参数E:

class AnimationManager<STATE extends Enum<STATE>>
...
void initAnimations(Player player, Heros chosen_hero, Class<STATE> heroStates)

Otherwise, if you do not know that STATE is an enum, then you can avoid the class reflection exercise of getting the enum types by letting the caller of your initAnimations() method provide them: 否则,如果您不知道STATE是一个枚举,则可以通过让initAnimations()方法的调用者提供它们来避免获取枚举类型的类反射练习:

void initAnimations(Player player, Heros chosen_hero, List<STATE> heroStates)
...
addAnimation(heroStates.get(i), frames.get(0), 15);

and the invocation would be something like 调用将类似于

AnimationManager<Foo> animationManager = ...;
animationManager.initAnimations(null, null, Arrays.asList(Foo.values()));

The third option, which I really don't like, would be to cast. 我真的不喜欢的第三个选择是强制转换。 In that case you just need to change the problematic line to 在这种情况下,您只需要将有问题的行更改为

addAnimation((STATE)heroStates.getEnumConstants()[i], frames.get(0), 15);

That will generate a warnings for an unchecked cast, which means the generics type system cannot guarantee that you're not ending up with ClassCastException s when you run your code. 这将为未经检查的强制转换生成警告,这意味着泛型类型的系统无法保证您在运行代码时不会以ClassCastException结尾。

Good luck with your game! 祝您比赛顺利!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM