新手自学关于java集合的疑问

夜龍 2013-08-03 03:16:56
小弟看书自学,看到java集合这里有点疑问,想了很久也上机试了还是搞不明白,求大神们指点!
import java.util.*;
public class IteratorTest
{
public static void main(String[] args)
{
Collection books = new HashSet();
books.add(new String("Java EE"));
books.add(new String("IOS"));
books.add(new String("Android"));
System.out.println(books);
Iterator it = books.iterator();
String b = (String)it.next(); //①
b = "aaa";
System.out.println(books);
}
}

这段代码是我用书上的范例改了改,运行结果如下:
[Android, IOS, Java EE]
[Android, IOS, Java EE]

对应的这段代码书上是这么讲解的:
当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传给了迭代变量,而是把集合元素的值传给了迭代变量,所以修改迭代变量的值对接元素本身没有任何影响。
所以我理解①处的b只是一个迭代变量,修改它并不会影响集合。

接着是这段代码:
import java.util.*;
public class Test {
private String a;
public Test(String a){
this.a = a;
}
public String toString(){
return "["+a+"]";
}
public static void main(String[] args){
HashSet hs = new HashSet();
hs.add(new Test("java"));
hs.add(new Test("c++"));
hs.add(new Test("ruby"));
System.out.println(hs);
//取出第一个元素
Iterator it = hs.iterator();
Test first = (Test)it.next();
//为第一个元素的a实例变量赋值
first.a = "C#";
System.out.println(hs);
}
}

这是书上的代码,结果如下:
[[java], [c++], [ruby]]
[[C#], [c++], [ruby]]

于是我的疑问就来了:这两段代码的区别无非是第一个用的String,第二个手动写了个类,修改的是类成员。为什么第二段代码用next()就能取出元素并修改。第一个不也是取出元素了吗,为啥修改了最后的结果又没有修改到集合呢?
于是我猜想,因为集合是保存的对象,而第一代码是修改的对象,第二个是修改的对象成员。是不是不能修改对象呢,只能修改对象成员呢?但是感觉这个猜想也不对,因为第一段代码书上说通过it.next()只是值传递,把值给了迭代变量,按照书上这段话理解,第一段代码的b和第二段代码的first只是迭代变量,修改它都不应该会对集合元素造成影响啊。为什么第二段代码又能修改了??
我晕了。。。
求大神指点!谢谢!!
...全文
175 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
夜龍 2013-08-03
  • 打赏
  • 举报
回复
谢谢各位!明白了,谢谢~!!
unknownxx 2013-08-03
  • 打赏
  • 举报
回复
引用 4 楼 xiangwangye66 的回复:
集合存储的是对象的存储地址,第一个例子中b变量拿到的是其实是对象的引用,修改变量b是不会修改对象的.但第二个例子first.a = "C#",first拿到的是对象的引用,然后first.a对对象的成员变量赋值所以改变了对象里的内容,最终打印的结果会改变.
正解。 这样理解楼主在书中看到的那一句:通过迭代器遍历集合时,返回的的确是集合中的一个元素值,只不过这个值就是元素的引用(地址),基于#4楼的解释,改变引用不会对元素造成影响。而你的第二个例子并不是“改变值”,而是改变了“值”(引用)指向的那个对象的“状态”(此例中你是改变了一个属性),因此你的第二个例子并不恰当。 第二个例子应该改成这样:first.a = "C#";——> first = new Test("C#"); 结果依然佐证了那句话想表达的意思。 此外,lz看到的书中的这句话,把“Iterator并不是把集合元素本身传给了迭代变量”这句去掉,理解剩下的就比较清晰了。
小杰68 2013-08-03
  • 打赏
  • 举报
回复
集合存储的是对象的存储地址,第一个例子中b变量拿到的是其实是对象的引用,修改变量b是不会修改对象的.但第二个例子first.a = "C#",first拿到的是对象的引用,然后first.a对对象的成员变量赋值所以改变了对象里的内容,最终打印的结果会改变.
gaobaiy 2013-08-03
  • 打赏
  • 举报
回复
当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传给了迭代变量,而是把集合元素的值传给了迭代变量,所以修改迭代变量的值对接元素本身没有任何影响 这句话要怎么理解?
gaobaiy 2013-08-03
  • 打赏
  • 举报
回复
这。。。不能证明这个问题吧,感觉这个例子本身有问题 String b = "aaa";创建了一个新的“aaa”对象,将使引用 b指向他, 执行完后,引用b表示了另一个对象,和原对象一点关系都没有 怎么可以证明 “当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传给了迭代变量,而是把集合元素的值传给了迭代变量,所以修改迭代变量的值对接元素本身没有任何影响。” 而System.out.println(hs); //取出第一个元素 Iterator it = hs.iterator(); Test first = (Test)it.next(); //为第一个元素的a实例变量赋值 first.a = "C#"; System.out.println(hs); 这段代码说明: (Test)it.next(); 是一个引用,指向堆中的内存地址,因为执行完以下两句 Test first = (Test)it.next(); first.a = "C#"; 对first的修改,表现到了集合中的对象 因此可以肯定it.next(); 返回的是一个对象引用 求大神详解啊!!!!
失落夏天 2013-08-03
  • 打赏
  • 举报
回复
String b = (String)it.next(); //① 这里传给b的是String型的值 那么这里的b应该是一个新的对象。//楼主可以做个实验试试,看看hashcode是不是一样的。 Test first = (Test)it.next(); 这里应该传入的是地址值吧。 传入的是地址值,如果你只是对这个地址值进行修改的话,我估计也不影响原对象, 但是如果你对这个地址值上的值进行修改,那应该就不行了吧。 个人感觉,有错请指出。。

62,616

社区成员

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

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