站内搜索: 请输入搜索关键词

当前页面: 开发资料首页J2SE 专题急+怪:定义了两个单独List类全局变量,操作一个List,另外一个List的值也跟着发生变化

急+怪:定义了两个单独List类全局变量,操作一个List,另外一个List的值也跟着发生变化

摘要: 急+怪:定义了两个单独List类全局变量,操作一个List,另外一个List的值也跟着发生变化


这个问题一直捆饶我几天了,一直都没有得到解决。情况是这样的,我在一个类中定义了两个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);

}
}




帮顶
顺便学习


那位兄弟过来指点一下。谢谢。。。


不应该吧,你看看是不是写错了?


什么地方写错了,,,就是找了好久没有找到原因。。。。



貌似没有错的地方啊


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




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


克隆出来的和被克隆两者是指向同一个对象。所以一起变化了。


调用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

楼主到上面的连接看看就清楚了



先谢谢楼上各位的解答,我先看看楼上给我的地址,研究一下,,下午有点事情去了,现在才回来,不好意思。。。。。


看了下克隆,还是没有看的很明白,,谁能给个例子吗?
我用下面的方法测试,怎么是可以的,我删除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的值:---------
姓名:张三
姓名:李四


谁能给个例子吗?就是一个列表填充另一个列表,被填充的列表元素值改变的时候,填充值不发生变化。


只要你的元素自己实现深拷贝,然后在拷贝过去就可以了


楼上的,能给个例子吗?



深层复制不好,会破坏原代码的结构!

写个例子给你看
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());
}
}




↑返回目录
前一篇: 求段java对象clone代码,解决马上结贴
后一篇: 为什么“.”不能做为分隔符?