大家,好!本人菜鸟,闲时,偶看重构,发现非常非常有帮助,但是先在在实际编程中遇到了个问题,不知道如何是“好”,特此求助!
问题表述:当用list做为参数时(可能有些狭隘,容器),如何在不改变list原来地址的内容而修改list,是否有一种克隆list的写法?用iterator?这地方我搞得就不太清楚。我要确保的一个原则是,方法的参数是用来看的,而不是用来改的。
希望大家发散思维,随便说说,就当交流了!
我也向各位老师好好学学!!!

解决方案 »

  1.   

    不明白LZ的意思,什么叫不改变list原来的地址,方法内部是改变不了外部变量的指向的
    也就是说
    List list = new ArrayList();change(List list) {
        list = new ArrayList(); //这里的改变是不影响上面的list的指向的
    }如果LZ的意思是list(容器)里的对象是不允许改变的,那么可以使用
    Collections.unmodifiableList(List<? extends T> list)即调用方法时
    change(Collections.unmodifiableList(list));
      

  2.   

    如何在不改变list原来地址的内容而修改listList newList = new ArrayList(list); //这样修改newList是不会影响list的,但没法保证list里存储的对象本身不被修改。因为newList里保存的是和list一样的对象,如果需要连list里保存的对象也不受影响,就要把list里的对象一个一个克隆。
      

  3.   

    LZ的意思是这样的:外面有个List l1调用方法 foo(l1)// foo(List list)
    foo里需要list的数据,并且随着方法的进行,需要对计算出来的数据临时保存到list(进行修改)但是,退出foo后又不能让foo中的修改更新到l1中简单的说,就是需要在foo中声明一个临时变量,它的内容和l1一模一样LZ俺说的对不 = =
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.List;public class A {
    public void foo(Collection<?> list) {
    ArrayList<Object> tmp = new ArrayList<Object>(list); for (int i = 0; i < tmp.size(); i++) {
    System.out.println(tmp.get(i));
    } if (tmp.contains("Hello")) {
    tmp.add("haha");
    } for (int i = 0; i < tmp.size(); i++) {
    System.out.println(tmp.get(i));
    }
    } public static void main(String args[]) {
    A a = new A(); List<String> list = new ArrayList<String>();
    list.add("Hello");
    list.add("World!"); a.foo(list); for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
    } }
    }
      

  4.   

    楼主说的修改list内容包括:添加,删除等操作吧。你可以把list的内容先save起来,等用完之后还原就可以了啊?不知道楼主的目的是什么?
      

  5.   

    LZ好像是说,把外部exlist的值传给了方法,而方法的inlist就与外部指向同一个地址了。
    这时如果在方法里操作了inlist地址的内容,那么就等于把外部的exlist的内容也改变了。如果只是为了一些查询之类的才调用方法,那不必担心啊。
    如果想同样修改一个list指向内容,而不破坏原来的,那复制一个不就行了。这时调用方法就传刚复制的那个地址。
      

  6.   

    我的意思与四楼相同,也就是说,当用list作为参数的时候(list中用来存放引用数据类型),如果要修改list中一些其他属性进行重新赋值,而依据重构的思想,参数是用来看的,而不是用来改的,那么我就要把list进行一下深度克隆,再把这个克隆好的list作为返回值返回到调用处。(老实说,我委实觉得这种做法有点脱裤子放屁,因为如果我直接修改参数中)传过来的list,这样的话连返回值都省了,但是我坚持我的做法,因为,至少我认为,调用一个没有返回值的方法,偷偷摸摸的改变了list中的值的做法是猥琐的,很容易让维护人员迷惑,所以,我坚持采用了克隆。(特附代码如下,请大家指出问题) public static Object deepClone(Object obj) throws IOException, ClassNotFoundException{
    ByteArrayOutputStream bo=new ByteArrayOutputStream();
    ObjectOutputStream oo=new ObjectOutputStream(bo);
    oo.writeObject(obj);
    ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
    ObjectInputStream oi=new ObjectInputStream(bi);
    Object result = oi.readObject() ;
    bo.close() ;
    oo.close() ;
    bi.close() ;
    oi.close() ;
    return result;
    }

    @SuppressWarnings("unchecked")
    public static List<?> deepCloneList(Iterator<?> pIterator) throws IOException, ClassNotFoundException{
    List result = new ArrayList() ;
    while(pIterator.hasNext()){
    result.add(deepClone( pIterator.next())) ;
    }
    return result;
    }
    另外,如果哪位老师觉得我的做法古怪或者不标准,哪怕是不好,非常可请您指出!!!
    或者是哪位老师认为就不应该克隆,请您指导!!!
      

  7.   


    你的形容很贴切  脱裤子放*1 首先你觉得在void方法中修改是猥琐的
    - 我没觉得猥琐 = = 如果你还是觉得猥琐,那么你可以修改完之后,将它返回,就可以不猥琐了2 很容易让维护人员迷惑
    - 清晰的注释、文档、方法名称、参数/变量名称都可以有效减少维护人员阅读代码的难度。
      比起直接修改,我反倒觉得你这样的做法更让人迷惑,克隆神马的不符合人的直观思维。

    - 我就不提克隆所作的额外工作对于整个项目的影响了。
      

  8.   

    恩!是我钻牛角尖了!
    我猥琐...
    其实,在重构里的要求是这样的,和大家分享一下,“可以修改参数对象的内部状态,但对参数对象重新赋值没有意义。”
    是我理解的太狭隘了,原话的意思应该是说,如果是引用数据类型的话,那么对其使用setter和getter方法是没问题的,但是如果是对象的重新赋值,就不ok了!
    也就是说,可以将参数全都设成是final的(当然,只要知道有这回事儿就好,过于短的函数没有必要设置成final的,函数如果过长的话还是可以起到辅助编程的作用。)。
    结贴!
    感谢11楼得一如既往!