
本文讲解如何设计 Dice 类,使其在创建时初始化面数(如 new Dice(6)),后续调用 rollDie() 时无需再次传入面数,直接复用对象内部的 sides 字段,提升代码简洁性与面向对象一致性。
本文讲解如何设计 dice 类,使其在创建时初始化面数(如 `new dice(6)`),后续调用 `rolldie()` 时无需再次传入面数,直接复用对象内部的 `sides` 字段,提升代码简洁性与面向对象一致性。
在面向对象编程中,对象的核心价值之一是封装状态与行为。你已将骰子的面数(sides)作为实例字段正确封装在 Dice 类中,但当前 rollDie(int sides) 方法仍要求每次调用都显式传参——这不仅违背封装原则,还容易引发逻辑不一致(例如误传 d6.rollDie(20) 导致六面骰返回 1–20 的值)。
✅ 正确做法是:提供无参重载方法 rollDie(),内部直接使用 this.sides。这样既保持接口简洁(d6.rollDie()),又确保行为始终与对象状态一致。
以下是优化后的完整代码:
// Dice.java
import java.util.Random;
public class Dice {
private final int sides; // 建议设为 final,面数创建后不应更改
public Dice(int sides) {
if (sides < 1) {
throw new IllegalArgumentException("骰子面数必须大于等于 1");
}
this.sides = sides;
}
// 有参版本(可保留,供特殊场景使用,但非推荐主接口)
public int rollDie(int sides) {
if (sides < 1) {
throw new IllegalArgumentException("面数必须大于等于 1");
}
return new Random().nextInt(sides) + 1; // 注意:nextInt(n) 返回 [0, n), 所以 +1 得 [1, n]
}
// ✅ 无参版本:自动使用对象自身状态
public int rollDie() {
return rollDie(this.sides); // 复用已有逻辑,避免重复代码
}
}// Main.java
public class Main {
public static void main(String[] args) {
Dice d6 = new Dice(6);
System.out.println("骰子面数:" + d6.sides); // 输出:6
System.out.println("掷骰结果:" + d6.rollDie()); // 输出:1–6 的随机整数(无需传参!)
System.out.println("再次掷骰:" + d6.rollDie()); // 每次调用独立随机
}
}? 关键改进点说明:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
- 移除冗余赋值:原 rollDie(int sides) 中 this.sides = sides 会意外覆盖构造时设定的面数,已删除;
- 修正随机逻辑:random.nextInt(sides + 1) + 1 实际生成 [1, sides+1],应改为 nextInt(sides) + 1 保证 [1, sides];
- 增强健壮性:添加参数校验,并将 sides 设为 final(推荐),防止运行时被意外修改;
- 方法复用:无参 rollDie() 直接委托给有参版本,避免逻辑重复,符合 DRY 原则。
? 延伸建议:
- 可进一步将 Random 实例提升为类字段(private static final Random RANDOM = new Random();),避免频繁创建对象;
- 若需支持多种骰子(如 d20, d100),可考虑使用枚举或工厂模式,但当前封装已满足核心需求。
通过这一设计,Dice 真正成为一个“有记忆”的对象——它知道自己是什么类型的骰子,并自主决定如何掷出合理结果。

















