声明:本博客为原创博客,未经允许,不得转载!原文链接为http://blog.csdn.net/bettarwang/article/details/28110615
最近放假,闲来无事,便翻看以前看过的一些书,竟然发现有些书本(甚至是一些畅销书)对Java中Iterator有很大的误解,比如某畅销书在Collection那一章有这么一句话:“当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传给了迭代变量,而是把集合元素的值传给了迭代变量,所以修改迭代变量的值对集合元素本身没有任何影响。”
我们先看它举的例子,代码如下(注:原文中字符串为中文,此处按个人偏好将其翻译成了英文):
import java.util.*; public class IteratorTest { public static void main(String[]args) { Collection books=new HashSet(); books.add("Light Java EE Practice"); books.add("Crazy Java Textbook"); books.add("Crazy Android Textbook"); Iterator it=books.iterator(); while(it.hasNext()) { String book=(String)it.next(); System.out.println(book); if(book.equals("Crazy Java Textbook")) { it.remove(); } book="Test String"; } System.out.println(books); } }其输出结果如下:
从这个输出结果来看:好像作者的结论挺对的。但是,其实这个结论很容易被证伪。如下面的一个例子:
import java.util.*; class Apple { int weight; public Apple(int weight) { this.weight=weight; } public String toString() { return "weight:"+weight; } } public class IteratorSample { public static void main(String[]args) { Collection collection=new HashSet(); Apple[]appleArray=new Apple[10]; for(int i=0;i<10;++i) { appleArray[i]=new Apple(i+200); collection.add(appleArray[i]); } System.out.println(collection); Iterator iterator=collection.iterator(); Apple apple=(Apple)iterator.next(); apple.weight=300; System.out.println(collection); } }输出结果如下:
显然,collection中的第一个元素被改变了。
那么到底为什么会出现这种看起来截然相反的两种结果呢?
问题就出在String上!在我的博客深刻理解Java中final的作用(一):从final的作用剖析String被设计成不可变类的深层原因一文中就讲过String是Java中一个很特殊的类,它的特殊之外就在于它是一个不可变类,即String对象一旦生成便不可改变,经常看到的对String变量的赋值其实是让引用指向新的String对象!
也就是说,在本文中第一个例子中,语句String book=(String)it.next();的作用只是让book也指向it.next()所指向的对象,后面book="Test String";只是让book这个引用指向一个新的字符串对象,显然这种改变不会也不可能影响原对象,it.next()所指向的另然是原来的那个对象,所以从结果来看好像作者的结论挺有道理。但是实际上Iterator.next()确实是提供了原对象的引用,对于除不可变类之外的其他对象,都可以通过这个引用来改变它(当然,也要有相应的接口)。本文中第二个例子就充分地说明了这一点,由于Apple并不是一个不可变类,故可通过iterator.next()来改变它指向的对象。
可能有人会质疑,为什么第一个例子中就不是让it.next()这个引用指向新的对象呢?原因很简单:book和it.next()是两个独立的引用,而程序中只对book进行了赋值,并没有对it.next()进行赋值。看下面一个简单的例子即可知:
import java.util.*; public class StringTest { public static void main(String[]args) { String str1="I miss you"; String str2=str1; System.out.println("str1:"+str1); System.out.println("str2:"+str2); str2="Will you miss me?"; System.out.println("str1:"+str1); System.out.println("str2:"+str2); } }输出结果如下:
显然,对str2的赋值根本就不影响str1,本文中第一个例子与其类似。
以前看书总是全盘接收,很少持怀疑态度,现在才发现“尽信书不如无书”,即使是畅销书,特别是国内的一些书籍,结论未必严谨。带着批判的角度去看书,多一些独立思考,方能有更大的收获。
畅销书对Java中Iterator的理解误区,布布扣,bubuko.com
原文地址:http://blog.csdn.net/bettarwang/article/details/28110615