modifying cloned objects
我正在尝试修改帐户对象,但是之后更改似乎不会出现在原始列表中。也许有人能找出错误。
见下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | if(aBank.getAccount(number)!=null){ System.out.println("Account information is listed below"); System.out.println(aBank.getAccount(number).toString()); System.out.println("Modify first name y or n"); answer=keyboard.nextLine(); if(answer.equals("Y")||answer.equals("y")){ System.out.println("Enter first name:"); firstName=keyboard.nextLine(); aBank.getAccount(number).getCustomer().setFirstName(firstName); } System.out.println("Modify last name y or n"); answer=keyboard.nextLine(); if(answer.equals("Y")|| answer.equals("y")){ System.out.println("Enter last name:"); lastName=keyboard.nextLine(); aBank.getAccount(number).getCustomer().setLastName(lastName); } } else{ System.out.println("Account not found"); } |
注意:getaccount(number)返回帐户的一个深度复制副本,getcustomer也返回一个深度复制副本。
GetAccount的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 | public Account getAccount(long accountNumber ) throws Exception { boolean found=false; for(int i=0;i<accounts.size();i++){ if(accounts.get(i).getAccountNumber().compareTo(accountNumber)==0){ found=true; return accounts.get(i).clone(); } } if (!found){ return null; } return null; } |
简单地调用docx1〔3〕不会返回对象的深度副本。它将返回一个浅显的副本。覆盖克隆很棘手。遵循Joshua Bloch从有效Java的建议,避免使用EDCOX1×3来支持复制构造函数。
1 2 3 4 5 6 7 8 | private Account(Account account) { this.name = account.getName(); //etc } public void createCopy(Account account) { return new Account(account); } |
另外,为什么不将帐户集合存储在地图中,这样在复制之前就不需要遍历N个帐户?你还需要仔细阅读布莱恩的答案。
如果
在这种情况下,您应该得到一个帐户的副本(通过
正如您所指出的,您正在修改副本。那个副本本身并没有连接到您的集合中,所以当您退出作用域时会丢失它。
另一个问题是,是否修改副本并重新插入是最佳解决方案。您可能希望在适当的位置进行修改,但这会使您面临各种各样的问题(例如线程处理——如果您在修改帐户的中途,而另一个客户端遍历列表并读取帐户详细信息,会发生什么情况?)