应使用private字段和public方法封装英雄属性与行为,如takedamage()统一处理伤害计算与血量更新,避免逻辑分散;scanner输入需统一用nextline()配合trim()防空格和换行符问题;加成规则宜用static final map配置,避免硬编码;nullpointerexception多因未实例化对象,需检查声明后是否new。

Java里怎么用类封装英雄属性
英雄不是一堆零散数字,而是有行为、有状态的实体。直接用int变量存血量、攻击力,很快就会失控——比如忘了同步更新防御力对实际伤害的影响,或者在多个地方重复写“血量不能为负”的逻辑。
应该用一个Hero类把数据和规则捆在一起:
public class Hero {
private int hp = 100;
private int attack = 20;
private int defense = 10;
<pre class='brush:java;toolbar:false;'>public void takeDamage(int rawDamage) {
int actual = Math.max(1, rawDamage - defense); // 至少掉1点
this.hp = Math.max(0, this.hp - actual);
}
public boolean isAlive() {
return this.hp > 0;
}}
- 所有字段必须是
private,暴露public方法控制修改入口 -
takeDamage()里做了两件事:算实际伤害、扣血——把业务规则锁死在类内部 - 别在构造器里做复杂计算或IO,初学者容易卡在这里等用户输入,导致类无法复用
为什么用Scanner读输入总出错
控制台交互最常崩在Scanner的换行符残留上。比如先用nextInt()读等级,再用nextLine()读名字,第二步会直接返回空字符串——因为nextInt()没吃掉回车符。
立即学习“Java免费学习笔记(深入)”;
统一用nextLine(),再手动转类型更稳:
Scanner sc = new Scanner(System.in);
System.out.print("请输入英雄等级:");
int level = Integer.parseInt(sc.nextLine().trim()); // 加trim防空格
System.out.print("请输入英雄名称:");
String name = sc.nextLine().trim();- 永远对
nextLine()结果调用trim(),Windows/Linux换行差异、用户多按空格都会导致name.equals("战士")失效 - 别用
hasNextInt()做校验——用户输"abc"时程序会卡住,要捕获NumberFormatException - 一个
Scanner对象够用,别每个输入都new一个,资源浪费且可能关错流
属性加成逻辑该放在Hero类里还是外面
加成规则(比如“每升一级攻击+5”“装备增加防御但降低命中”)本质是业务变化点。如果硬编码在Hero的levelUp()方法里,以后策划改数值就得改Java代码,编译重跑。
把规则抽成配置,用简单结构承载:
public class Hero {
private int level = 1;
private static final Map<Integer, Integer> ATTACK_PER_LEVEL = Map.of(
1, 20, 2, 25, 3, 30 // 等级→基础攻击
);
<pre class='brush:java;toolbar:false;'>public void levelUp() {
if (this.level < 3) {
this.level++;
this.attack = ATTACK_PER_LEVEL.get(this.level);
}
}}
- 初学者容易把Map写成全局static但不加
final,结果被误改;或者用new HashMap()然后忘记put,查半天空指针 - 别为了“看起来灵活”立刻上JSON配置文件——控制台小工具里,
Map.of()或数组足够,过早抽象反而难调试 - 加成逻辑如果涉及多个属性联动(如“暴击率=攻击/100”,但攻击又受装备影响),就用
getAttack()这类getter封装计算,别让外部直接读字段
运行时报错Exception in thread "main" java.lang.NullPointerException
这个错误90%是因为某个Hero变量声明了但没new。比如写了Hero hero;就直接调hero.takeDamage(10),JVM找不到实际对象。
检查三处高频漏点:
- 主方法里是否漏了
Hero hero = new Hero();?只声明不实例化是新手最常犯的错 - 如果用了
List<hero></hero>存多个英雄,add()前是否每个元素都new了?list.add(null)之后再取出来用必崩 - 从方法返回
Hero时,是否在所有分支都写了return?比如if-else里else缺return,静态分析可能放过,但运行时返回null
只要出现NullPointerException,第一反应不是看堆栈第几行,而是顺着报错行往上找——那个点名的变量,最近一次赋值是不是null或根本没赋过值。











