繁体   English   中英

在聚合类中使用克隆的最佳实践

[英]The best practice using clone in an aggregated class

我有一个系统,其中有一个客户,其补充的ArrayList作为其属性。

客户类的代码是:

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);
    }

最初,我的setSuppList方法仅包含一行代码,即suppList = list,而我的getSuppList方法只是“ return suppList”。 我觉得这是一次隐私泄漏,因此我在这两种方法中都称为克隆。 对于setSuppList,suppList = new ArrayList()并遍历参数列表并克隆每个对象,并将其添加到suppList数组中。 对于getSuppList,它遍历suppList并克隆其中的每个Supplement对象,将其添加到新数组中并返回该数组。 但是,我意识到,如果将补充对象的价格从$ 3更改为$ 50,并且如果我有100个客户,则意味着我必须继续调用setSuppList()100x。

我改变了主意,因此将setSuppList方法更改为suppList = list,并将克隆内容仅保留在getSuppList中。

然后想到了...为什么我不将suppList作为setSuppList中的新数组,并将参数“ list”中的每个项目添加到suppList中。 这样,list和suppList都引用相同的对象,但是当list删除一个项目时,Customer对象的suppList保持不受影响。 只是当单个项目受到影响时,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)
{

}

}

输出量

克隆数组大小:2

删除克隆数组中的项目后

克隆数组大小:1

从getSuppList返回的数组大小:2

数组大小:2

如果我将第一组奖品中的第一项更改为50

第一个数组中的对象的第一项价格:50.0

getSuppList返回的数组中对象中第一项的价格:2.9

如果我直接将补充对象更改为40

第一个数组中的对象的第一项价格:50.0

getSuppList返回的数组中对象中第一项的价格:40.0

但是,当我尝试这样做时,会有意外的行为。 spList.get(0).setWeeklyCost(50); 不会影响Customer对象的suppList对象。

怎么可能? spList和suppList都引用相同的对象,尽管它们是不同的数组。

由于Supplement是其自身的东西,与Customer完全不同,并且可以自己重命名和重新定价,因此您永远不应将其克隆为Customer逻辑的一部分。

您应该“克隆” 列表 ,因为那是客户的属性,可以通过调用copy-constructor轻松完成:

suppList = new ArrayList<>(list);

spList.get(0).setWeeklyCost(50); 不会影响Customer对象的suppList对象。 怎么可能 ??

因为当您调用cstmr.getSuppList()时仍在克隆Supplement

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM