遇到个奇怪问题,来看看

JPF1024 2016-03-10 08:22:22

import java.util.ArrayList;
import java.util.List;

/**
* List遇到的问题.
* <p>
* <p>
* <p>
* Created by prd on 2016/03/10.
*/
public class Main {

public static void main(String[] args) {
List<List<String>> lists = new ArrayList<>();
List<String> newlists = new ArrayList<>();
for (int i = 0; i < 5; i++) {
/*
本意是在这里删除newlists里面的所有元素,
全部重新添加.

发现用了clear无效果,但将:
List<String> newlists = new ArrayList<>();
放在循环内则可正常运行.
*/
newlists.clear();
for (int j = 0; j < 10; j++) {
StringBuffer str = new StringBuffer();
str.append("this -> " + j + " , " + i);
newlists.add(str.toString());
}
lists.add(newlists);
}

for (int i = 0; i < lists.size(); i++) {
for (int j = 0; j < lists.get(i).size(); j++) {
System.out.println(lists.get(i).get(j));
}
System.out.println("-------------------------------");
}

}
}





错误的运行结果【注意最后一个数字】:

this -> 0 , 4
this -> 1 , 4
this -> 2 , 4
this -> 3 , 4
this -> 4 , 4
this -> 5 , 4
this -> 6 , 4
this -> 7 , 4
this -> 8 , 4
this -> 9 , 4
-------------------------------
this -> 0 , 4
this -> 1 , 4
this -> 2 , 4
this -> 3 , 4
this -> 4 , 4
this -> 5 , 4
this -> 6 , 4
this -> 7 , 4
this -> 8 , 4
this -> 9 , 4
-------------------------------
this -> 0 , 4
this -> 1 , 4
this -> 2 , 4
this -> 3 , 4
this -> 4 , 4
this -> 5 , 4
this -> 6 , 4
this -> 7 , 4
this -> 8 , 4
this -> 9 , 4
-------------------------------
this -> 0 , 4
this -> 1 , 4
this -> 2 , 4
this -> 3 , 4
this -> 4 , 4
this -> 5 , 4
this -> 6 , 4
this -> 7 , 4
this -> 8 , 4
this -> 9 , 4
-------------------------------
this -> 0 , 4
this -> 1 , 4
this -> 2 , 4
this -> 3 , 4
this -> 4 , 4
this -> 5 , 4
this -> 6 , 4
this -> 7 , 4
this -> 8 , 4
this -> 9 , 4
-------------------------------


下面是可以正常运行的代码:


import java.util.ArrayList;
import java.util.List;

/**
* List遇到的问题.
* <p>
* <p>
* <p>
* Created by prd on 2016/03/10.
*/
public class Main {

public static void main(String[] args) {
List<List<String>> lists = new ArrayList<>();

for (int i = 0; i < 5; i++) {
/*
本意是在这里删除newlists里面的所有元素,
全部重新添加.

发现用了clear无效果,但将:
List<String> newlists = new ArrayList<>();
放在循环内则可正常运行.
*/
List<String> newlists = new ArrayList<>();
//newlists.clear();
for (int j = 0; j < 10; j++) {
StringBuffer str = new StringBuffer();
str.append("this -> " + j + " , " + i);
newlists.add(str.toString());
}
lists.add(newlists);
}

for (int i = 0; i < lists.size(); i++) {
for (int j = 0; j < lists.get(i).size(); j++) {
System.out.println(lists.get(i).get(j));
}
System.out.println("-------------------------------");
}

}
}


想要的结果:

this -> 0 , 0
this -> 1 , 0
this -> 2 , 0
this -> 3 , 0
this -> 4 , 0
this -> 5 , 0
this -> 6 , 0
this -> 7 , 0
this -> 8 , 0
this -> 9 , 0
-------------------------------
this -> 0 , 1
this -> 1 , 1
this -> 2 , 1
this -> 3 , 1
this -> 4 , 1
this -> 5 , 1
this -> 6 , 1
this -> 7 , 1
this -> 8 , 1
this -> 9 , 1
-------------------------------
this -> 0 , 2
this -> 1 , 2
this -> 2 , 2
this -> 3 , 2
this -> 4 , 2
this -> 5 , 2
this -> 6 , 2
this -> 7 , 2
this -> 8 , 2
this -> 9 , 2
-------------------------------
this -> 0 , 3
this -> 1 , 3
this -> 2 , 3
this -> 3 , 3
this -> 4 , 3
this -> 5 , 3
this -> 6 , 3
this -> 7 , 3
this -> 8 , 3
this -> 9 , 3
-------------------------------
this -> 0 , 4
this -> 1 , 4
this -> 2 , 4
this -> 3 , 4
this -> 4 , 4
this -> 5 , 4
this -> 6 , 4
this -> 7 , 4
this -> 8 , 4
this -> 9 , 4
-------------------------------

有大神可以解释下这是为啥吗?谢谢。



...全文
259 12 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
jiar2046 2016-03-15
  • 打赏
  • 举报
回复
引用 11 楼 PJ_Richard 的回复:
[quote=引用 9 楼 jiar2046的回复:][quote=引用 7 楼 PJ_Richard 的回复:] [quote=引用 2 楼 jiar2046的回复:]实际上就和c里的指针一样。第一种方法中,外围list中保存的都是同一个子list的引用。所对应的对象都是最后一次改变的子list。
初学java,想请教大神,Map.Entry是Map中的静态嵌套借口,调用是怎么不是Map.Map.Entry,而是直接Map.Entry?[/quote] 额,我也才学。。不是大神只是渣渣。。。 没太明白你的问题。。为什么调用时要Map.Map.Entry啊?[/quote] 就想静态内部类一样,如class Wi{ static class Nei{} } class Other{ Wi.Nei p=new Wi().new Nei() } !!是这样吧? Interface Map{ static Interface Map.Entry{} }那么在其他类中建立它的对象(当然是多态),不应该和上面类似吗?[/quote] 额~~java.util.Map 的源码是: public interface Map<K,V>{ 。。。。。 。。。。。 interface Entry<K,V>{ } 。。。。。 } 在其他包中调用内部接口的话 应该是 java.util.Map.Entry<x,y> 额~~ 我也不是很清楚这一块。只是感觉是内部接口和外部接口可以被分别实现,编译后与单独的写成两个接口时类似。不过内部接口的路径在外部接口之下。
PJ_Richard 2016-03-12
  • 打赏
  • 举报
回复
引用 9 楼 jiar2046的回复:
[quote=引用 7 楼 PJ_Richard 的回复:] [quote=引用 2 楼 jiar2046的回复:]实际上就和c里的指针一样。第一种方法中,外围list中保存的都是同一个子list的引用。所对应的对象都是最后一次改变的子list。
初学java,想请教大神,Map.Entry是Map中的静态嵌套借口,调用是怎么不是Map.Map.Entry,而是直接Map.Entry?[/quote] 额,我也才学。。不是大神只是渣渣。。。 没太明白你的问题。。为什么调用时要Map.Map.Entry啊?[/quote] 就想静态内部类一样,如class Wi{ static class Nei{} } class Other{ Wi.Nei p=new Wi().new Nei() } !!是这样吧? Interface Map{ static Interface Map.Entry{} }那么在其他类中建立它的对象(当然是多态),不应该和上面类似吗?
PJ_Richard 2016-03-11
  • 打赏
  • 举报
回复
引用 2 楼 jiar2046的回复:
实际上就和c里的指针一样。第一种方法中,外围list中保存的都是同一个子list的引用。所对应的对象都是最后一次改变的子list。
初学java,想请教大神,Map.Entry是Map中的静态嵌套借口,调用是怎么不是Map.Map.Entry,而是直接Map.Entry?
月凉西厢 2016-03-11
  • 打赏
  • 举报
回复
如果在循环内部新建,因为是不同的newLists,肯定没有问题。 如果在循环外面,那每次都是同一个newLists,而ArrayList.add添加的是引用,类似于C的指针,这就可能存在问题。 但是,问题并不在这里!只要仔细看下字符串的构建就会发现很奇怪的地方 str.append("this -> " + j + " , " + i); 难道这里也是对j和i的引用?!因为str,append只是将三段字符串拼接,并没有生成一个新的长的String,那i一直输出最终的4就可以理解了,但是为什么 j 就没有一直输出10呢?诡异
  • 打赏
  • 举报
回复
楼主对于"对象"或者说"类的实例"概念还比较模糊。 这样说吧,在这段程序代码中,有几个new就有几个对象。 假如把newList放在外面,那么实际上你只new了两个对象。 而假如放在里面,那就是十一个对象。 其中一个对象是外层循环 在错误的结果里,内层循环始终都是一个值,因为它只有一个对象。 而在正确的结果里,内层循环是十个值,因为它有十个对象。 实际上调用clear方法在这个程序里没有意义。
三仙半 2016-03-11
  • 打赏
  • 举报
回复
引用 2 楼 jiar2046 的回复:
实际上就和c里的指针一样。第一种方法中,外围list中保存的都是同一个子list的引用。所对应的对象都是最后一次改变的子list。
同意二楼的观点
JPF1024 2016-03-11
  • 打赏
  • 举报
回复
引用 2 楼 jiar2046 的回复:
实际上就和c里的指针一样。第一种方法中,外围list中保存的都是同一个子list的引用。所对应的对象都是最后一次改变的子list。
正解。
jiar2046 2016-03-11
  • 打赏
  • 举报
回复
引用 7 楼 PJ_Richard 的回复:
[quote=引用 2 楼 jiar2046的回复:]实际上就和c里的指针一样。第一种方法中,外围list中保存的都是同一个子list的引用。所对应的对象都是最后一次改变的子list。
初学java,想请教大神,Map.Entry是Map中的静态嵌套借口,调用是怎么不是Map.Map.Entry,而是直接Map.Entry?[/quote] 额,我也才学。。不是大神只是渣渣。。。 没太明白你的问题。。为什么调用时要Map.Map.Entry啊?
疯狂熊猫人 2016-03-11
  • 打赏
  • 举报
回复
1、和clear没有半毛钱关系。clear每次都是会清理掉newlists 所指向的集合的所有元素 2、那么为什么i的结果一直为4呢?而j一直都会变呢?并且输出了5次,原因分析: a 每次调用newlists .clear()都是在循环的开头部分,所以第5次循环结束后,newlists 实际是有值的(无法进入第6次循环),并且此时i的值正好是4。这就是j的值在变,但i一直为4的原因 b 每次循环的末尾,都有一个lists.add(newlists),所以,5次循环后lists中就会存在5个对newlists的引用,这是为什么会打印出5次相同结果的原因
so1ene 2016-03-10
  • 打赏
  • 举报
回复
又想了一下,就是单纯的引用关系,而且之前变量因为引用的存在(次数未清零)并没有被回收,之前想错了。
jiar2046 2016-03-10
  • 打赏
  • 举报
回复
实际上就和c里的指针一样。第一种方法中,外围list中保存的都是同一个子list的引用。所对应的对象都是最后一次改变的子list。
so1ene 2016-03-10
  • 打赏
  • 举报
回复
刚学JAVA,尝试答一下。 我觉得好像不是clear()的问题,而是List.add方法的问题。 第一个中(把newlists放在for循环内的),在每次add(newlists)时,上一个newlists已经结束(即两次不是同一个newlists); 而第二个(把newlists作为class变量),在每次add(newlists)时,与上一次的newlists还是同一个newlists,只是它们的值不一样。 在输出lists时候,第一个中,输出的是之前add的每个在下一次add之前就已经结束的newlists; 而第二个中,add的所有列表都是同一个newlists,并且这个newlists现在仍然存在,输出时输出的是这个newlists的当前值,比如可以在第二个程序的第二个for( for (int i = 0; i < lists.size(); i++) {)之前修改newlists的值,输出的都是修改后的newlists的值。 这里我觉得List.add方法好像这样的:如果add的变量存在的话,是add一个对于该变量的一个引用,而当这个变量结束时,才会保存下这个变量在结束时的值。 新人尝试答一下,错了还请谅解。

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧