聲明:本博客爲原創博客,未經允許,不得轉載!原文鏈接爲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,本文中第一個例子與其類似。
以前看書總是全盤接收,很少持懷疑態度,現在才發現“盡信書不如無書”,即使是暢銷書,特別是國內的一些書籍,結論未必嚴謹。帶着批判的角度去看書,多一些獨立思考,方能有更大的收穫。