向ArrayList添加不同元素却重复最新项?TableView商品加购物车异常
问题分析与解决方案
这种问题我之前踩过坑!大概率是复用了同一个商品对象实例导致的,咱们一步步拆解问题:
核心原因
你提到添加Apple时正常,但添加Melon后列表里出现两个重复的最新项,这说明两次添加的其实是同一个对象的引用——当你选中Melon时,修改了这个共享对象的属性,之前添加的Apple引用指向的也是这个对象,所以最终列表里的两个元素看起来都是Melon。
举个错误代码的例子,你可能是这么写的:
// 错误:全局复用同一个Product对象 Product product = new Product(); // 监听选中事件,修改同一对象的属性 tableView.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal) -> { product.setDesc(newVal.getDesc()); product.setId(newVal.getId()); product.setPrice(newVal.getPrice()); }); // 点击按钮时,把同一个对象加入列表 addButton.setOnAction(e -> { order.add(product); shoppingCart.addOrder(order); });
解决方法
每次点击添加按钮时,创建一个全新的商品对象实例,把选中商品的属性复制进去,再加入order列表:
方法1:手动复制属性
addButton.setOnAction(e -> { Product selected = tableView.getSelectionModel().getSelectedItem(); if (selected == null) return; // 防止空选中 // 创建新对象,复制选中项的所有属性 Product newProduct = new Product(); newProduct.setDesc(selected.getDesc()); newProduct.setId(selected.getId()); newProduct.setPrice(selected.getPrice()); order.add(newProduct); shoppingCart.addOrder(order); });
方法2:用拷贝构造函数(更优雅)
如果你的Product类定义了拷贝构造函数,代码会更简洁:
// 先给Product类加拷贝构造函数 public class Product { private String desc; private String id; private double price; // 拷贝构造函数 public Product(Product other) { this.desc = other.desc; this.id = other.id; this.price = other.price; } // 其他构造函数、getter/setter... } // 添加按钮的事件处理 addButton.setOnAction(e -> { Product selected = tableView.getSelectionModel().getSelectedItem(); if (selected == null) return; Product newProduct = new Product(selected); order.add(newProduct); shoppingCart.addOrder(order); });
验证方式
可以在添加后打印每个商品对象的哈希码,确认是不是不同实例:
for (Product p : order) { System.out.println(p.getDesc() + " - 对象哈希码:" + System.identityHashCode(p)); }
如果两个元素的哈希码不同,说明是不同实例,问题就解决了;如果哈希码相同,那还是实例复用的问题,再检查代码里的对象创建逻辑。
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

