Java静态变量total累加翻倍异常问题求助(附代码)
问题:静态变量累加发票总价时出现翻倍异常
我在Java程序里用静态变量total记录发票总价,每次用户输入新商品价格后用+=累加,但总价没有正确更新,反而出现金额翻倍的情况。尝试在增强for循环里嵌套普通for循环迭代这个静态变量,问题还是没解决。
原代码:
// 主逻辑部分 while(isRunning) { try { System.out.println("Please enter the name of your item you want to add: (type quit to exit) "); String item = input.nextLine(); if(item.equalsIgnoreCase("quit")) { break; } System.out.println("Please enter the price of the item to be added to the invoice. "); receipt.setTotal(input.nextDouble()); input.nextLine(); itemList itemlist = new itemList(item, Invoice.total); price.add(itemlist); } catch (InputMismatchException e) { System.out.println("Exception caught!"); } for(Invoice itemization : price) { Invoice.total += itemization.getTotal(); System.out.println(); System.out.println("Item: " + itemization.getItem() + "\nPrice: " + itemization.getTotal()); System.out.println("Subtotal: " + Math.round(receipt.getTotal() * 100.00) / 100.00); } // 类定义部分 import java.util.*; public class Invoice { static Double total; public String item; List<Invoice> price = new ArrayList<>(); public String getItem() { return item; } public double getTotal() { return total; } public void setTotal(Double total) { Invoice.total = total; } public void endBalance() { if (getTotal() > 0.0) { System.out.println(); System.out.println("$" + getTotal() + " Will be deposited once cleared. "); System.out.println(); System.out.println("Expect most transfer to deposit to your account with 3 to 5 business days. "); System.out.println(); } else { System.out.println("Available balance too low for bank deposit. "); } } } class itemList extends Invoice { public itemList(String item, Double total) { this.item = item; } }
问题根源:
- 静态变量共享导致覆盖:
Invoice.total是静态变量,所有Invoice子类实例共用同一个值。每次调用setTotal都会直接覆盖全局的total,而不是存储当前商品的价格。 - 重复累加逻辑错误:每次添加商品后,都会遍历整个商品列表对全局
total进行累加,相当于把所有商品的价格又加了一遍,导致总价多次翻倍。 - 类职责混乱:
itemList继承Invoice完全不合理,商品不是发票的子类,而且构造函数没有存储传入的价格,所有实例的getTotal()都返回全局静态变量的值,进一步加剧重复累加。
修复方案:
拆分职责,去掉静态变量,用非静态变量维护总价,修正累加逻辑:
import java.util.ArrayList; import java.util.List; import java.util.Scanner; import java.util.InputMismatchException; // 发票类:管理商品列表和总价 public class Invoice { private List<Item> items = new ArrayList<>(); private double total = 0.0; // 添加商品并更新总价 public void addItem(Item item) { items.add(item); total += item.getPrice(); } // 获取保留两位小数的总价 public double getFormattedTotal() { return Math.round(total * 100.0) / 100.0; } // 打印所有商品明细和当前小计 public void printItemization() { for (Item item : items) { System.out.println(); System.out.println("商品: " + item.getName() + "\n价格: " + item.getPrice()); } System.out.println("\n小计: " + getFormattedTotal()); } // 打印最终到账信息 public void endBalance() { if (total > 0.0) { System.out.println(); System.out.println("确认到账金额: $" + getFormattedTotal()); System.out.println(); System.out.println("预计转账将在3-5个工作日内存入您的账户。"); System.out.println(); } else { System.out.println("可用余额过低,无法进行银行转账。"); } } } // 商品类:存储单个商品的名称和价格 class Item { private String name; private double price; public Item(String name, double price) { this.name = name; this.price = price; } public String getName() { return name; } public double getPrice() { return price; } } // 主程序 public class InvoiceApp { public static void main(String[] args) { Scanner input = new Scanner(System.in); boolean isRunning = true; Invoice receipt = new Invoice(); while (isRunning) { try { System.out.println("请输入要添加的商品名称(输入quit退出): "); String itemName = input.nextLine(); if (itemName.equalsIgnoreCase("quit")) { break; } System.out.println("请输入该商品的价格: "); double itemPrice = input.nextDouble(); input.nextLine(); // 清除输入后的换行符 Item newItem = new Item(itemName, itemPrice); receipt.addItem(newItem); receipt.printItemization(); } catch (InputMismatchException e) { System.out.println("输入错误!请输入有效的数字价格。"); input.nextLine(); // 清除错误输入,避免死循环 } } receipt.endBalance(); input.close(); } }
修复关键点:
- 拆分
Invoice和Item的职责,逻辑更清晰,避免继承滥用。 - 用
Invoice的非静态total变量维护总价,每次添加商品时只累加当前商品价格,不会重复计算。 - 移除静态变量,避免全局共享导致的值覆盖问题。
- 优化输入异常处理,避免死循环。
内容的提问来源于stack exchange,提问作者dankest germ
相关产品推荐
相关产品推荐

