有一个Hashmap(o),它将字符串作为键,将Order Object作为值。 Order有一个OrderLines的Arraylist。在这里,我必须向地图添加多个订单。问题是我的hashmap打印出唯一的第一个和第二个键(order 1和Order 2),但最后插入的值作为两个键的值(所有条目中的重复顺序)。你能帮我调试一下这个问题吗?
主要类:
Map<String, Order> o = new HashMap<String, Order>();
Order c = new Order();
c.add(new OrderLine(new Item("book", (float) 12.49), 1));
c.add(new OrderLine(new Item("music CD", (float) 14.99), 1));
o.put("Order 1", c);
// Reuse cart for an other order
c.clearCart(); // this.orderLines.clear() in the order class
c.add(new OrderLine(new Item("imported box of chocolate", 10), 1));
c.add(new OrderLine(new Item("imported bottle of perfume", (float) 47.50), 1));
o.put("Order 2", c);
for (Map.Entry<String, Order> entry : o.entrySet()) {
System.out.println("*******" + entry.getKey() + entry.getValue().get(0).getItem().getDescription() + "*******");
}
订购类:
class Order {
private List<OrderLine> orderLines = new ArrayList<>();
public void add(OrderLine o) throws Exception {
orderLines.add(o);
}
public OrderLine get(int i) {
return orderLines.get(i);
}
public void clearCart() {
this.orderLines.clear();
}
}
OrderLine类:
private int quantity;
private Item item;
public OrderLine(Item item, int quantity) throws Exception {
if (item == null) {
System.err.println("ERROR - Item is NULL");
throw new Exception("Item is NULL");
}
assert quantity > 0;
this.item = item;
this.quantity = quantity;
}
public Item getItem() {
return item;
}
public int getQuantity() {
return quantity;
}
}
项目类:
class Item {
private String description;
private float price;
public Item(String description, float price) {
super();
this.description = description;
this.price = price;
}
public String getDescription() {
return description;
}
public float getPrice() {
return price;
}
}
答案 0 :(得分:2)
虽然Java是按值传递的,但改变引用末尾的内容是完全有效的。这就是你正在做的事情,虽然不经意间。
考虑一下您在做什么:您将c
添加到列表中,然后清除c,
重新初始化,然后重新添加。
由于您从未使用new
关键字,因此您实际上从未为c.
分配新的内存部分它仍指向相同的Order.
同时,您没有添加列表中c
的克隆。您添加了c.
换句话说,当您拨打c.clearCart(),
时,您还要清除列表Order
中的第一个o
,因为Order
是 { {1}}
您可以通过替换以下来使用c.
关键字:
new
与
c.clearCart();
或者,您可以将c = new Order();
的克隆添加到列表c
而不是o
本身,这样当您致电c
时,您无法清除第一个元素list c.clearCart(),
换句话说,替换:
o.
与
o.put("Order 1", c);
有关详细信息,请参阅this question。
修改强>
我忘记了一部分,虽然这可能很明显。我已声明清除o.put("Order 1", c.clone());
也会清除列表c
中的第一个元素,因为该元素是 o,
但是,我忘记提及,通过转换,重新 - 初始化c.
也意味着同时重新初始化这个元素。因此,当您再次添加c
时,您有两个使用相同字段初始化的元素。