这个问题一直捆饶我几天了,一直都没有得到解决。情况是这样的,我在一个类中定义了两个List全局变量,一个List的元素是用另外一个List填充的。但是操作被填充的List,另外填充的List的值一起发生变化了,基本的流程就是,teachers列表的数据是从数据库查询出来的,只需要查询一次就可以了,然后把teachers列表作为一个列表元素添加到offerArragingteachers列表里面,我这里用的是add()方法,我在给offerArragingTeachers列表增加元素的时候是定义了一个新的列表,并且把teachers列表的内容clone到这个新定义的列表,然后才add到offerArragingTeachers,然后在addTeacherToArragedList()方法中,根据request的值,从session(这个就是offerArragingTeachers第几个元素的索引)位置列表取出相应的记录添加到offerArrangedTeachers列表,但是问题出现了,,我操作offerArragingTeachers列表的元素,teachers的列表数据跟着发生变化了,不知道什么原因,期待高手解决。。代码如下:   public class TeacherContainer {     private List teachers = new ArrayList(); // 教师列表     // 未安排的所有老师
     private List offerArragingTeachers = new ArrayList(); 
     // 已安排的监考老师
     private List offerArrangedTeachers = new ArrayList();      //给offerArragingTeachers列表新增元素
     public void add() {
if (teachers.size() <= 0) {
                        //这里是从数据库查询数据
teachers = teacherService.query();
}
List newEmptyTeachers = (List) ((ArrayList) teachers).clone();
offerArragingTeachers.add(newEmptyTeachers);
} public void addTeacherToArragedList(int session, String majorTeacher) { // 监考老师需求数量
int request = this.getRequestInvigilateAmount(); List sessionOfArragingTeacher = new ArrayList();
try {
sessionOfArragingTeacher = (List) offerArragingTeachers
.get(session);
} catch (IndexOutOfBoundsException e) {
// 增加一个新的场次教师资源列表
this.add();
List newEmptyTeachers = new ArrayList();
newEmptyTeachers.addAll(teachers);
sessionOfArragingTeacher.addAll(newEmptyTeachers);
} // 得到给定场次所有安排的监考老师
List arragedInvigilateTeacher = new ArrayList();
try {
arragedInvigilateTeacher = (List) offerArrangedTeachers
.get(session);
} catch (IndexOutOfBoundsException e) {
offerArrangedTeachers.add(session, errorDefaultValue);
} for (int i = 0; i < request; i++) {
Teacher teacher = (Teacher) sessionOfArragingTeacher.get(0);
// 将已经安排的老师从列表中清除
                        // (问题:)这里删除一列值,那么teachers列表也相应的删除了一列值
sessionOfArragingTeacher.remove(0);
// 将此老师加入到已安排的监考老师列表
arragedInvigilateTeacher.add(teacher);
} // 更新老师资源列表
offerArragingTeachers.set(session, sessionOfArragingTeacher);
// 更新已安排监考老师列表
offerArrangedTeachers.set(session, arragedInvigilateTeacher); }
  }

解决方案 »

  1.   

    try {
    sessionOfArragingTeacher = (List) offerArragingTeachers.get(session);//发生异常运行下面的程序
    } catch (IndexOutOfBoundsException e) {
    // 增加一个新的场次教师资源列表
    this.add();
    List newEmptyTeachers = new ArrayList();
    newEmptyTeachers.addAll(teachers);
    sessionOfArragingTeacher.addAll(newEmptyTeachers);//包含了teachers对象
    }
      

  2.   

    个人觉得是:JAVA克隆的问题,你没有实现克隆方法,是调用系统的clone,
    是不是?
    系统默认的是浅克隆,你要是是深度克隆。
      

  3.   

    调用Object类中clone()方法产生的效果是:先在内存中开辟一块和原始对象一样的空间,然后原样拷贝原始对象中的内容。对基本数据类型,这样的操作是没有问题的,但对非基本类型变量,我们知道它们保存的仅仅是对象的引用,这也导致clone后的非基本类型变量和原始对象中相应的变量指向的是同一个对象。 大多时候,这种clone的结果往往不是我们所希望的结果,这种clone也被称为"影子clone"。要想让b2.unCA指向与b2.unCA不同的对象,而且b2.unCA中还要包含b1.unCA中的信息作为初始信息,就要实现深度clone。 怎么进行深度clone?
     http://www.smatrix.cn/bbs/simple/index.php?t11646.html楼主到上面的连接看看就清楚了
      

  4.   

    看了下克隆,还是没有看的很明白,,谁能给个例子吗?
    我用下面的方法测试,怎么是可以的,我删除offerList列表指定元素里面的值不影响emptyList的值,为什么我上面的那样写就不行。
    public class test { private static List offerList = new ArrayList();
    private static List emptyList = new ArrayList(); public static void main(String[] args) throws ParseException{
    operList();
    }

    public static void add(){
    if (emptyList.isEmpty()){
    Teacher t1 = new Teacher();
    t1.setName("张三");
    t1.setIsntavile("Y");
    t1.setIsntinvigilate("Y");
    emptyList.add(t1); Teacher t2 = new Teacher();
    t2.setName("李四");
    t2.setIsntavile("Y");
    t2.setIsntinvigilate("Y");
    emptyList.add(t2); }
     List newList = (List) ((ArrayList) emptyList).clone();
    offerList.add(newList);
    }

    public static void operList(){

    add();
    System.out.println("---------变化前基础数据emptyList的值:---------");
    for (int i = 0; i < emptyList.size(); i++){
    Teacher t = (Teacher) emptyList.get(i);
    System.out.println("姓名:"+t.getName());
    }

    System.out.println("---------总数据offerList的值:---------");
    List firstValue = (List) offerList.get(0);
    firstValue.remove(0);
    add();
    add();

    List secondValue = (List) offerList.get(1);
    secondValue.remove(1);

    for (int o = 0; o < offerList.size(); o++){
    List thisList = (List) offerList.get(o);
    System.out.println("列表位置:--------第"+o+"个");
    for (int i = 0; i < thisList.size(); i++){
    Teacher t = (Teacher) thisList.get(i);
    System.out.println("姓名:"+t.getName());
    }
    }

    System.out.println("---------变化后基础数据emptyList的值:---------");
    for (int i = 0; i < emptyList.size(); i++){
    Teacher t = (Teacher) emptyList.get(i);
    System.out.println("姓名:"+t.getName());
    }
    }
    }
    -----------------------------------------------------------------
    测试结果:---------变化前基础数据emptyList的值:---------
    姓名:张三
    姓名:李四
    ---------总数据offerList的值:---------
    列表位置:--------第0个
    姓名:李四
    列表位置:--------第1个
    姓名:张三
    列表位置:--------第2个
    姓名:张三
    姓名:李四
    ---------变化后基础数据emptyList的值:---------
    姓名:张三
    姓名:李四
      

  5.   

    深层复制不好,会破坏原代码的结构!写个例子给你看
    public class Classroom implements Cloneable{
        public Object clone() throws CloneNotSupportedException
    return super.clone();
        }
    }
    在你原先的类上面加个接口Cloneable,还得覆写clone() 方法。最后,你还是得:
    public void add(){
        Iterator it=emptyClassroom.iterator();
        while(it.hasNext()){
             offerClassroom.add((Classroom)it.next()).clone());
        }
    }