
本文详解为何创建多个JuiceStore对象时库存(leftJuices)未按预期全局减少,并通过static关键字或单例设计实现共享状态,附可运行代码示例与关键注意事项。
本文详解为何创建多个juicestore对象时库存(leftjuices)未按预期全局减少,并通过`static`关键字或单例设计实现共享状态,附可运行代码示例与关键注意事项。
在面向对象编程中,每个对象都拥有自己独立的一份实例变量副本——这是理解本问题的核心。题中代码创建了三个 JuiceStore 实例(Juice1、Juice2、Juice3),每个实例的 leftJuices 都被初始化为 3,且彼此完全隔离:
JuiceStore Juice1 = new JuiceStore(14); // leftJuices = 3(仅属于Juice1) JuiceStore Juice2 = new JuiceStore(7); // leftJuices = 3(仅属于Juice2) JuiceStore Juice3 = new JuiceStore(17); // leftJuices = 3(仅属于Juice3)
因此,当调用 Juice1.buyJuice() 时,仅 Juice1.leftJuices 从 3 减至 2;Juice2 和 Juice3 的库存仍为初始值 3,后续调用各自 buyJuice() 也只影响自身状态。最终三者库存均为 2,而非期望的“全局剩余 0”。
✅ 正确方案一:使用 static 变量(适用于共享状态场景)
将 leftJuices 声明为 static,使其成为类级别变量,所有实例共享同一份数据:
public class JuiceStore {
private int temperature;
private static int leftJuices = 3; // ← 关键修改:static 使变量全局唯一
public JuiceStore(int temperature) {
this.temperature = temperature;
}
public void buyJuice() throws NoJuiceException, TooColdException, TooWarmException {
if (leftJuices < 1) {
throw new NoJuiceException("Unfortunately, there is no juice left. Come back tomorrow.");
}
leftJuices--; // 直接操作静态变量(无需 this.)
System.out.println("You have bought a juice, there are " + leftJuices + " left.");
if (temperature < 9) throw new TooColdException("The juice is too cold.");
if (temperature > 15) throw new TooWarmException("The juice is too warm.");
System.out.println("Drink successful.");
}
}⚠️ 注意事项:
立即学习“Java免费学习笔记(深入)”;
- static 变量属于类而非对象,不适用于需要多套独立库存的场景(如不同门店);
- 在多线程环境中需额外加锁(如 synchronized)保证线程安全,否则可能出现竞态条件;
- static 成员不能直接访问非静态成员(如 this.temperature 是合法的,但若在静态方法中访问 temperature 则编译报错)。
✅ 正确方案二:单例模式(更可控的全局状态管理)
若需封装逻辑、避免全局污染,推荐使用单例:
public class JuiceStore {
private static JuiceStore instance;
private int temperature;
private int leftJuices = 3;
private JuiceStore() {} // 私有构造防止外部实例化
public static JuiceStore getInstance() {
if (instance == null) {
instance = new JuiceStore();
}
return instance;
}
public void setTemperature(int temp) {
this.temperature = temp;
}
public void buyJuice() throws NoJuiceException, TooColdException, TooWarmException {
if (leftJuices < 1) {
throw new NoJuiceException("Unfortunately, there is no juice left. Come back tomorrow.");
}
leftJuices--;
System.out.println("You have bought a juice, there are " + leftJuices + " left.");
if (temperature < 9) throw new TooColdException("The juice is too cold.");
if (temperature > 15) throw new TooWarmException("The juice is too warm.");
System.out.println("Drink successful.");
}
}主程序改为统一调用单例:
public class Program {
public static void main(String[] args) {
JuiceStore store = JuiceStore.getInstance();
try {
store.setTemperature(14);
store.buyJuice(); // 剩余: 2
store.setTemperature(7);
store.buyJuice(); // 剩余: 1
store.setTemperature(17);
store.buyJuice(); // 剩余: 0 → 下次抛出 NoJuiceException
} catch (NoJuiceException | TooColdException | TooWarmException e) {
System.out.println(e.getMessage());
}
}
}? 总结
- ❌ 错误根源:误将需共享的状态(总库存)定义为实例变量;
- ✅ 推荐选择:
- 快速验证/简单场景 → 使用 static;
- 工程化项目/需扩展性 → 采用单例或依赖注入容器管理共享资源;
- ? 核心原则:状态归属决定变量类型——实例状态用 private 实例变量,跨对象共享状态必须显式设计(static、单例、外部仓库等)。










