Java 在聚合类中使用克隆的最佳实践
我有一个系统,其中有一个客户,其属性是补充剂的数组列表 客户类别的代码为:Java 在聚合类中使用克隆的最佳实践,java,clone,Java,Clone,我有一个系统,其中有一个客户,其属性是补充剂的数组列表 客户类别的代码为: public class Customer implements Cloneable { . . ArrayList<Supplement> suppList public Customer(String fName, String lName, String emailInput, ArrayList<Supplement> list
public class Customer implements Cloneable
{
.
.
ArrayList<Supplement> suppList
public Customer(String fName, String lName, String emailInput, ArrayList<Supplement> list)
{
setFName(fName);
setLName(lName);
setEmailAddr(emailInput);
setSuppList(list);
}
public void setSuppList(ArrayList<Supplement> list)
{
suppList = new ArrayList<Supplement>();
for(Supplement sp : list)
{
suppList.add(sp);
}
}
}
public ArrayList<Supplement> getSuppList() throws CloneNotSupportedException
{
ArrayList<Supplement> list = new ArrayList<Supplement>();
if (suppList != null)
{
for(Supplement sp : suppList)
{
list.add((Supplement)sp.clone());
}
}
return list;
}
public void addSupp(Supplement item)
{
suppList.add(item);
}
public void removeSupp(Supplement item)
{
suppList.remove(item);
}
公共类客户实现可克隆
{
.
.
ArrayList支持列表
公共客户(字符串fName、字符串lName、字符串emailInput、ArrayList列表)
{
setFName(fName);
setLName(lName);
setEmailAddr(emailInput);
设置支持列表(列表);
}
公共无效设置列表(ArrayList列表)
{
suppList=newarraylist();
用于(补充sp:列表)
{
添加(sp);
}
}
}
public ArrayList getSuppList()引发CloneNotSupportedException
{
ArrayList=新建ArrayList();
if(suppList!=null)
{
对于(补充sp:供应清单)
{
添加((补充)sp.clone());
}
}
退货清单;
}
公共无效添加支持(补充项)
{
供应清单。添加(项目);
}
公共无效删除支持(补充项)
{
供应清单。删除(项目);
}
最初,我的setSuppList方法只包含一行代码,即suppList=list,而我的getSuppList方法只是“return suppList”。
我觉得这是一个隐私泄露,所以我在两种方法上都称之为克隆。
对于setSuppList,suppList=new ArrayList(),它遍历参数列表,克隆每个对象并将其添加到suppList数组中。
对于getSuppList,它迭代suppList并克隆其中的每个补充对象,将其添加到新数组中并返回数组。
但是,我意识到,如果将一个补充对象的价格从3美元更改为50美元,并且如果我有100个客户,这意味着我必须继续调用setSuppList()100x
我改变了主意,所以我将setSuppList方法更改为suppList=list,并将克隆内容仅保留在getSuppList中
然后我想到。。。为什么不在setSuppList中将suppList设置为一个新数组,并将参数“list”中的每一项添加到suppList中呢。
这样,list和suppList都引用相同的对象
但是,当列表删除一个项目时,Customer对象的suppList不会受到影响。
仅当单个项目受到影响时,供应商列表会相应更新(例如,补遗的价格)
当我想在suppList中添加或删除项目时,我可以使用addSupp方法、removeSupp方法或setSuppList方法
public static void main(String[] args)
{
try
{
Supplement s1 = new Supplement("A", 2.9);
Supplement s2 = new Supplement("B", 3);
ArrayList<Supplement> spList = new ArrayList<Supplement>();
spList.add(s1);
spList.add(s2);
Customer cstmr = new Customer("killua", "zoldyck", "killua@gmail.com", spList);
ArrayList<Supplement> spList2 = cstmr.getSuppList();
System.out.println("cloned array size : "+spList2.size());
spList2.remove(0);
System.out.println("After removing an item in the cloned array");
System.out.println("cloned array size : "+spList2.size());
System.out.println("Array returned from getSuppList size : "+cstmr.getSuppList().size());
spList.remove(0);
System.out.println("array size : "+cstmr.getSuppList().size());
System.out.println("");
spList.get(0).setWeeklyCost(50);
System.out.println("If I change the first item in the first array prize to 50");
System.out.println("price of 1st item in object in the first array : "+spList.get(0).getWeeklyCost());
System.out.println("price of 1st item in object in the array returned by getSuppList : "+cstmr.getSuppList().get(0).getWeeklyCost());
System.out.println("");
s1.setWeeklyCost(40);
System.out.println("If I change the supplement object directly to 40");
System.out.println("price of 1st item in object in the first array : "+spList.get(0).getWeeklyCost());
System.out.println("price of 1st item in object in the array returned by getSuppList : "+cstmr.getSuppList().get(0).getWeeklyCost());
}
catch(CloneNotSupportedException e)
{
}
publicstaticvoidmain(字符串[]args)
{
尝试
{
补编s1=新补编(“A”,2.9);
补编s2=新补编(“B”,3);
ArrayList spList=新的ArrayList();
spList.add(s1);
spList.add(s2);
客户cstmr=新客户(“killua”、“zoldyck”、”killua@gmail.com“,spList);
ArrayList spList2=cstmr.getSuppList();
System.out.println(“克隆数组大小:+spList2.size());
spList2.删除(0);
System.out.println(“删除克隆数组中的项后”);
System.out.println(“克隆数组大小:+spList2.size());
System.out.println(“从getSuppList size返回的数组:+cstmr.getSuppList().size());
spList.remove(0);
System.out.println(“数组大小:+cstmr.getSuppList().size());
System.out.println(“”);
spList.get(0.setWeeklyCost(50);
System.out.println(“如果我将第一个数组中的第一个项目更改为50”);
System.out.println(“第一个数组中对象中第一项的价格:”+spList.get(0.getWeeklyCost());
System.out.println(“getSuppList返回的数组中对象中第一项的价格:”+cstmr.getSuppList().get(0.getWeeklyCost());
System.out.println(“”);
s1.设置每周成本(40);
System.out.println(“如果我将补充对象直接更改为40”);
System.out.println(“第一个数组中对象中第一项的价格:”+spList.get(0.getWeeklyCost());
System.out.println(“getSuppList返回的数组中对象中第一项的价格:”+cstmr.getSuppList().get(0.getWeeklyCost());
}
捕获(CloneNotSupportedException e)
{
}
}
输出
克隆阵列大小:2
删除克隆阵列中的项后
克隆数组大小:1
从getSuppList返回的数组大小:2
阵列大小:2
如果我将第一个阵列中的第一个项目更改为50
第一个数组中对象中第一项的价格:50.0
getSuppList返回的数组中对象中第一项的价格:2.9
如果我直接将补充对象更改为40
第一个数组中对象中第一项的价格:50.0
getSuppList返回的数组中对象中第一项的价格:40.0
然而,当我尝试这样做时,出现了一种意想不到的行为。spList.get(0.setWeeklyCost(50);不影响客户对象的suppList对象
这怎么可能?spList和suppList都引用相同的对象,尽管它们是不同的数组…因为
增补
是它自己的东西,与客户
完全不同,并且可以自己重命名和重新定价,所以绝不能将其克隆为客户
逻辑的一部分
您应该“克隆”列表,因为这是客户的属性,通过调用复制构造函数可以轻松完成:
suppList = new ArrayList<>(list);
suppList=newarraylist(列表);
spList.get(0.setWeeklyCost(50);不影响客户对象的suppList对象。怎么可能呢
由于调用
cstmr.getSuppList()
时您仍在克隆Supplement
,因为Supplement
是它自己的东西,与Customer
完全不同,并且可以自己重命名和重新定价,所以您不应该将其克隆为Customer
逻辑的一部分
您应该“克隆”列表,因为这是客户的属性,通过调用复制构造函数可以轻松完成:
suppList = new ArrayList<>(list);
suppList=newarraylist(列表);