Java RPG游戏中从ArrayList访问子类并在ListView显示名称的问题
解决方案
核心问题分析
- 静态变量导致的name获取错误:你把
name定义成了static变量,静态变量属于类而非实例。当用父类Enemy的引用指向子类实例时,访问的永远是父类的static name,而非子类的。 - ListView默认显示对象地址:ListView会默认调用对象的
toString()方法,而默认的toString()返回的是类名+内存地址,所以你看到了com.example.test.Swordsman@x这类内容。
步骤1:修正Enemy类的设计(关键)
把所有静态成员改为实例成员,让每个敌人实例拥有自己的属性,子类通过构造方法初始化自身属性:
Enemy父类:
public class Enemy { protected String name = "Enemy"; protected int damage = 1; protected int hp = 1; protected int defense = 1; protected int mana = 1; protected int speed = 1; protected int luck = 1; // 重写toString(),直接返回name,方便ListView显示 @Override public String toString() { return this.name; } }
Swordsman子类:
public class Swordsman extends Enemy { public Swordsman() { // 初始化子类独有的属性值 this.name = "Swordsman"; this.damage = 3; this.hp = 15; this.defense = 2; this.mana = 1; this.speed = 1; this.luck = 15; } }
Archer子类(同理):
public class Archer extends Enemy { public Archer() { this.name = "Archer"; // 填入Archer对应的属性值 this.damage = 4; this.hp = 10; // ...其他属性 } }
步骤2:优化ListView显示(两种可选方式)
方式1:利用重写的toString()(最简单)
因为已经在Enemy类里重写了toString()返回name,所以你原来的添加代码只需小改,ListView会自动显示敌人的名称:
public void battle() { if (!prep) { ArrayList<Enemy> classes = new ArrayList<>(); classes.add(new Swordsman()); classes.add(new Archer()); Random random = new Random(); for (int i = 0; i < 3; i++) { // 随机选一个敌人添加到ListView int randomIndex = random.nextInt(classes.size()); battleOptions.getItems().add(classes.get(randomIndex)); } prep = true; // 标记prep为true,避免重复添加 } }
方式2:自定义CellFactory(更灵活,适合复杂显示)
如果之后需要显示更多信息(比如敌人的HP、伤害),可以用CellFactory自定义ListView的显示内容:
// 在初始化ListView的地方设置CellFactory battleOptions.setCellFactory(listView -> new ListCell<Enemy>() { @Override protected void updateItem(Enemy enemy, boolean empty) { super.updateItem(enemy, empty); if (empty || enemy == null) { setText(null); } else { // 自定义显示内容,比如"剑士 (HP:15)" setText(enemy.name + " (HP:" + enemy.hp + ")"); } } });
额外优化建议
- 把自定义的
randomnumber方法替换成Java标准的Random类,更可靠:new Random().nextInt(2)就能生成0或1的随机数。 - 子类的属性值如果是比例(比如原来的0.3),可以改成具体数值(比如3),更符合RPG游戏的数值逻辑,或者保留double类型但统一单位。
内容的提问来源于stack exchange,提问作者Real Darkflare
相关产品推荐
相关产品推荐

