天天看点

不可变(Immutable)字符串

JAVA平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地,你可以使用StringBuffers来动态构造字符数据。

但是String类是内容不可改变的字符串

.1.2 不可变(Immutable)字符串

在Java中使用字符串有一个非常重要的规则必须记得, 一个字符串对象一旦被配置,它的内容就是固定不可变的。例如下面这个声明:

String str = "caterpillar";       

这个声明会配置一个长度为11、内容为caterpillar的字符串对象,您无法改变这个字符串对象的内容。不要以为下面的语句就是改变一个字符串对象的内容:

String str = "Just";       
str = "Justin";       

事实上在这个程序片段中会有两个字符串对象,一个是Just字符串对象,长度为4;一个是Justin字符串对象,长度为6,两个是不同的字符串对象。您并不是在Just字符串后加上in字符串,而是让str名称引用自Justin字符串对象。图6-2展示出了这个概念。

不可变(Immutable)字符串

图6-2  使用=作字符串指定的意义 在Java中,使用“=”将一个字符串对象指定给一个变量名称,其意义为改变该名称所引用的对象,原来被引用的字符串对象若没有其他名称来引用它,就会在适当的时候被Java的“垃圾回收”(Garbage Collection)机制回收。在Java中,程序设计人员通常不用关心无用对象的资源释放问题,Java会检查对象是否不再被引用,没有被任何名称引用的对象将会被回收。 在 Java 执行时会维护一个 String 池 (Pool) 。对于一些可以共享的字符串对象,会先在 String 池中查找是否存在相同的 String 内容 ( 字符相同 ) ,如果有就直接返回,而不是直接创造一个新的 String 对象,以减少内存的耗用。如果在程序中使用下面的方式来声明,则实际上是指向同一个字符串对象:

String str1 = "flyweight";      
String str2 = "flyweight";       
System.out.println(str1 == str2);      

当直接在程序中使用 "" 来包括一个字符串时,该字符串就会在 String 池中,上面的程序片段中的 flyweight 就是这样的情况。 flyweight 在程序中会有一个实例,而 str1 与 str2 同时引用自 flyweight 。图 6-3 表示了这个概念。

不可变(Immutable)字符串

图6-3  字符串变量str1、str2同时引用自flyweight 在 Java 中如果 == 被使用于两个对象类型的变量,它是用于比较两个变量是否引用自同一对象,所以在图6-3中当str1==str2比较时,程序的执行结果会显示true。 再来看看关于String的intern()方法,先看一下API说明的节选(翻译): 在intern()方法被调用时,如果池(Pool)中已经包括了相同的String对象(相同与否由equals()方法决定),那么会从池中返回该字符串,否则原String对象会被加入池中,并返回这个String对象的引用。 这段话其实说明了Flyweight模式(参见本章的网络索引) 的运作方式,直接使用范例6.4来说明会更清楚。 Ü 范例6.4  InternString.java                                                      public class InternString {     public static void main(String[] args) {         String str1 = "fly";         String str2 = "weight";         String str3 = "flyweight";         String str4 = null;           str4 = str1 + str2;         System.out.println(str3 == str4);           str4 = (str1 + str2).intern();         System.out.println(str3 == str4);     } }   style='使用图形来说明这个范例,在声明str1、str2、str3后,String池中的状况如图6-4所示。  

不可变(Immutable)字符串
不可变(Immutable)字符串

图6-4  字符串池示意 在Java中,使用+串联字符串会产生一个新的字符串对象,所以在程序中第一次比较str3与str4对象是否为同一对象时,结果会是false,如图6-5所示。

不可变(Immutable)字符串

图6-5  字符串加法会产生新的字符串 intern()方法会先检查String池中是否存在字符部分相同的字符串对象,如果有就返回。由于程序中之前已经声明flyweight字符串对象,intern()在String池中发现了它,所以直接返回。这时再进行比较,str3与str4所指向的其实会是同一对象,所以结果会是true,如图6-6所示。

不可变(Immutable)字符串

图6-6  intern()会返回String池中字符串对象的引用 由以上的说明也得出一个结论,==在Java中被用来比较两个变量名称是否 引用自同一对象,所以不可以用 == 来比较两个字符串的字符内容是否相同 。例如:

String str1 = new String("caterpillar");      
String str2 = new String("caterpillar");      
System.out.println(str1 == str2);      

虽然两个字符串对象的字符值完全相同,但实际上在这个程序片段中,产生了两个 String 的实例, str1 与 str2 分别引用自不同的实例。所以使用 == 比较时结果会显示 false 。如果要比较两个字符串对象的字符值是否相同,要使用 equals() 方法 ,以下的写法才会显示 true 的结果:

String str1 = new String("caterpillar");      
String str2 = new String("caterpillar");      
System.out.println(str1.equals(str2));      

 http://book.csdn.net/bookfiles/135/1001354627.shtml