Java 在setter中使用switch语句

Java 在setter中使用switch语句,java,setter,Java,Setter,这可能是一个非常愚蠢的问题,但我想我应该试着问一下!基本上,问题是:我可以在setter中使用switch语句吗 我正在做的是:我创建了一个怪物类,它的属性有healthPoints、description、damage和type,其中type是一个枚举。在我的驱动程序中,我编写了几行代码,这些代码将根据枚举值随机生成一个怪物类型,它将使用该类型创建一个新的怪物 问题是,当我显示怪物统计数据时,它显示健康点和伤害为0,描述为空。当我尝试使用默认Monster构造函数运行程序时,它崩溃并显示Nul

这可能是一个非常愚蠢的问题,但我想我应该试着问一下!基本上,问题是:我可以在setter中使用switch语句吗

我正在做的是:我创建了一个怪物类,它的属性有healthPoints、description、damage和type,其中type是一个枚举。在我的驱动程序中,我编写了几行代码,这些代码将根据枚举值随机生成一个怪物类型,它将使用该类型创建一个新的怪物

问题是,当我显示怪物统计数据时,它显示健康点和伤害为0,描述为空。当我尝试使用默认Monster构造函数运行程序时,它崩溃并显示NullPointerException错误

我认为错误在我的setter或构造函数中。每个设定者里面都有一个开关盒,根据随机生成的怪物类型设定一定数量的健康点、伤害和特定描述。我不确定在setter中使用switch语句是否合适,因为我以前从未真正需要这样做

这是我的一些代码。首先,我的构造函数

public Monster(int healthPoints, monsterType type, int damage, String description)
{
    setHealthPoints(healthPoints);
    setType(type);
    setDamage(damage);
    setDescription(description);
}

public Monster(monsterType type)
{
    setType(type);
}
下面是一个设定者

public void setHealthPoints(int healthPoints)
{
    switch(type)
    {
        case DROW: 
            healthPoints = 30;
            break;
        case LICH:
            healthPoints = 40;
            break;
        case ORC:
            healthPoints = 20;
            break;
        case OWLBEAR:
            healthPoints = 20;
            break;
        case RUST_MONSTER:
            healthPoints = 10;
            break;
    }
    this.healthPoints = healthPoints;
}
下面是驱动程序中创建怪物的线条

int number = new Random().nextInt(monsterType.values().length);
        Monster monster = new Monster(monsterType.values ()[number]);
我希望怪物的生命值、伤害和描述根据生成的怪物类型来设置。我不确定这是否可以通过设置器中的开关来实现,我觉得我的错误可能是显而易见的,我只是没有看到它,因为我已经盯着它看了很长时间……或者,如果有不同或更简单的方法来实现,请让我知道!感谢您抽出时间阅读;我试图把我的问题/问题弄清楚。

解释 是的,您可以在构造函数和方法中使用
开关
案例。问题是您在
setType
之前调用
setHealthPoints
,但第一种方法在其
开关
语句中使用
type

setHealthPoints(healthPoints);
setType(type);
因此,当您访问
设置健康点
开关时,变量
类型
未初始化,因此当前
为空

如果
switch
语句的参数为
null
,则该语句将抛出
NullPointerException
。这样就得到了NPE

您可以通过首先执行
setType
来解决此问题


关于游戏架构的建议 您应该创建一个更可读的结构,该结构也更易于维护,尤其易于扩展

请考虑创建一个<代码>怪物>代码>强>接口<强>或>强>抽象类< /强>。之后,创建显式怪物作为子类。类
怪物
将包含所有怪物中平等的一切,尝试从特定的怪物中抽象出来。怪物本身将只包含与其他怪物不同的东西

例如,您可以使用以下类型:

public abstract class Monster {
    private int mHealthPoints;
    private int mDamage;
    private String mDescription;

    public Monster(int healthPoints, int damage, String description) {
        this.mHealthPoints = healthPoints;
        this.mDamage = damage;
        this.mDescription = description;
    }

    public int getHealthPoints() {
        return this.mHealthPoints;
    }

    public int getDamage() {
        return this.mDamage;
    }

    public String getDescription() {
        return this.mDescription;
    }
}
然后你有特定的怪物类,比如

public class Orc extends Monster {
    private static int HEALTH = 20;
    private static int DAMAGE = 10;
    private static String DESCRIPTION = "Nasty orc.";

    public Orc() {
        super(Orc.HEALTH, Orc.DAMAGE, Orc.DESCRIPTION);
    }
}
您也不再需要
怪物类型
枚举,因为您可以通过Orc的
怪物实例
进行区分。然而,对于真正的模块化设计,您不应该在特定的类上工作。相反,使用大量描述属性和能力的接口

例如,接口如下:

CanAttack
IsAttackable
HasHealth
CanWalk
CanFly
CanCollide
...
您的游戏逻辑可能只建立在这些接口上。例如,
CanAttack
可能看起来像:

public interface CanAttack {
    void attack(IsAttackable target);
}
最大的优势是你可以轻松地扩展你的游戏。例如,通过创建具有任意能力组合的怪物:

public SuperFlyingPig extends Monster implements
        CanAttack, HasHealth, CanWalk, CanFly {
    ...
}

它将神奇地工作,没有任何额外的编码工作,因为您的逻辑将不关心特定的怪物。它只适用于接口

我认为您应该使您的结构更容易阅读。使用
Monster
作为接口,然后创建显式子类,如
Drow
Lich
Orc
Owlbear
RustMonster
,它们都实现了
Monster
。如果你的
怪物
的代码在所有这些怪物中都是相等的,那么你也可以将你的
怪物
变成一个抽象类。然后,该代码转到
Monster
,而其余代码转到子类。然后确定共同的结构,怪物应该只包含使他们独一无二的其他。比如一个变量maximalHealth左右。setter本身对所有人都是一样的。您的问题之一似乎是您的第一个构造函数应该在调用setHealthPoints()之前调用
setType()
。后一种方法取决于(明显的)实例变量
type
。请遵守命名约定。类应以大写字符开头。因此,您的
enum
应该改为
MonsterType
。完整的答案解释了问题以及如何解决问题,此外,还通过展示如何改进当前代码来实现。做得好。