??xml version="1.0" encoding="utf-8" standalone="yes"?>欧美男人天堂,最色在线观看,色综合视频网站http://www.aygfsteel.com/gkc/category/42149.htmlgkczh-cnTue, 13 Oct 2009 12:22:32 GMTTue, 13 Oct 2009 12:22:32 GMT60d理解java Stringhttp://www.aygfsteel.com/gkc/articles/298042.htmlgkcgkcTue, 13 Oct 2009 03:56:00 GMThttp://www.aygfsteel.com/gkc/articles/298042.htmlhttp://www.aygfsteel.com/gkc/comments/298042.htmlhttp://www.aygfsteel.com/gkc/articles/298042.html#Feedback0http://www.aygfsteel.com/gkc/comments/commentRss/298042.htmlhttp://www.aygfsteel.com/gkc/services/trackbacks/298042.html 

一、创建?br /> 好了Q知道String是非可变cM后,我们可以q一步了解String的构造方式了。创Z个Stirng对象Q主要就有以下两U方式:
java 代码

1. String str1 = new String("abc");
2. Stirng str2 = "abc";

 

虽然两个语句都是q回一个String对象的引用,但是jvm对两者的处理方式是不一L。对于第一U,jvm会马上在heap中创Z个String对象Q然后将该对象的引用q回l用戗对于第二种Qjvm首先会在内部l护的strings pool中通过String?equels Ҏ查找是对象池中是否存放有该String对象Q如果有Q则q回已有的String对象l用P而不会在heap中重新创Z个新的String对象Q如果对象池中没有该String对象Qjvm则在heap中创建新的String对象Q将其引用返回给用户Q同时将该引用添加至strings pool中。注意:使用W一U方法创建对象时Qjvm是不会主动把该对象放到strings pool里面的,除非E序调用 String的internҎ。看下面的例子:
java 代码

1. String str1 = new String("abc"); //jvm 在堆上创Z个String对象
2.
3. //jvm 在strings pool中找不到gؓ“abc”的字W串Q因?
4. //在堆上创Z个String对象Qƈ该对象的引用加入至strings pool?
5. //此时堆上有两个String对象
6. Stirng str2 = "abc";
7.
8. if(str1 == str2){
9. System.out.println("str1 == str2");
10. }else{
11. System.out.println("str1 != str2");
12. }
13. //打印l果?str1 != str2,因ؓ它们是堆上两个不同的对象
14.
15. String str3 = "abc";
16. //此时Qjvm发现strings pool中已?#8220;abc”对象了,因ؓ“abc”equels “abc”
17. //因此直接q回str2指向的对象给str3Q也是说str2和str3是指向同一个对象的引用
18. if(str2 == str3){
19. System.out.println("str2 == str3");
20. }else{
21. System.out.println("str2 != str3");
22. }
23. //打印l果?str2 == str3

再看下面的例子:
java 代码

1. String str1 = new String("abc"); //jvm 在堆上创Z个String对象
2.
3. str1 = str1.intern();
4. //E序昑ּstr1攑ֈstrings pool中,internq行q程是这LQ首先查看strings pool
5. //有没“abc”对象的引用,没有Q则在堆中新Z个对象,然后新对象的引用加入至
6. //strings pool中。执行完该语句后Qstr1原来指向的String对象已经成ؓ垃圾对象了,随时?
7. //被GC攉?
8.
9. //此时Qjvm发现strings pool中已?#8220;abc”对象了,因ؓ“abc”equels “abc”
10. //因此直接q回str1指向的对象给str2Q也是说str2和str1引用着同一个对象,
11. //此时Q堆上的有效对象只有一个?
12. Stirng str2 = "abc";
13.
14. if(str1 == str2){
15. System.out.println("str1 == str2");
16. }else{
17. System.out.println("str1 != str2");
18. }
19. //打印l果?str1 == str2
20.

Z么jvm可以q样处理String对象呢?是因ؓString的非可变性。既然所引用的对象一旦创建就怸更改Q那么多个引用共用一个对象时互不影响?/p>


二、串接(ConcatenationQ?br /> javaE序员应该都知道滥用String的串接操作符是会影响E序的性能的。性能问题从何而来呢?归根l底是Stringcȝ非可变性。既?String对象都是非可变的Q也是对象一旦创Z׃能够改变其内在状态了Q但是串接操作明显是要增长字W串的,也就是要改变String的内部状态,两者出C矛盾。怎么办呢Q要l护String的非可变性,只好在串接完成后新徏一个String 对象来表C新产生的字W串了。也是_每一ơ执行串接操作都会导致新对象的生,如果串接操作执行很频J,׃D大量对象的创建,性能问题也就随之而来了?br /> Z解决q个问题Qjdk为StringcL供了一个可变的配套c,StringBuffer。用StringBuffer对象Q由于该cL可变的,串接时仅仅时改变了内部数据结构,而不会创建新的对象,因此性能上有很大的提高。针对单U程Qjdk 5.0q提供了StringBuilderc,在单U程环境下,׃不用考虑同步问题Q用该cM性能得到q一步的提高?/p>

三、String的长?br /> 我们可以使用串接操作W得C个长度更长的字符Ԍ那么QString对象最多能容纳多少字符呢?查看String的源代码我们可以得知cString中是使用?count 来记录对象字W的数量Q而count 的类型ؓ intQ因此,我们可以推测最长的长度?2^32Q也是4G?br /> 不过Q我们在~写源代码的时候,如果使用 Sting str = "aaaa";的Ş式定义一个字W串Q那么双引号里面的ASCII字符最多只能有 65534 个。ؓ什么呢Q因为在class文g的规范中Q?CONSTANT_Utf8_info表中使用一?6位的无符h数来记录字符串的长度的,最多能表示 65536个字节,而java class 文g是用一U变体UTF-8格式来存攑֭W的Qnullg用两个字节来表示Q因此只剩下 65536Q?2 Q?65534个字节。也正是变体UTF-8的原因,如果字符串中含有中文{非ASCII字符Q那么双引号中字W的数量会更(一个中文字W占用三个字节)。如果超个数量,在编译的时候编译器会报错?/p>

对Stringcȝ理解|上有很多的资料Q个得很多都是错误的Q错误的解释危害性更大。所以ؓ了解释清楚,来看代码,代码q行出的l果才是最h说服力的。说明:以下都是个h的理解,Ƣ迎指正?br /> Java代码 复制代码

1. public class StringTest {
2. public static void main(String[] args) {
3. String str1 = new String("abc");
4.
5. String str2 = "abc";
6.
7. if (str1 == str2) {
8. System.out.println("str1 == str2");
9. } else {
10. System.out.println("str1 != str2");
11. }
12.
13. String str3 = "abc";
14. if (str2 == str3) {
15. System.out.println("str2 == str3");
16. } else {
17. System.out.println("str2 != str3");
18. }
19.
20. str1 = str1.intern();
21.
22. if (str1 == str2) {
23. System.out.println("str1 == str2");
24. } else {
25. System.out.println("str1 != str2");
26. }
27.
28. String str4 = new String("abc");
29. str4 = str4.intern();
30.
31. if (str1 == str4) {
32. System.out.println("str1 == str4");
33. } else {
34. System.out.println("str1 != str4");
35. }
36. }
37.
38. }


q行l果Q?/p>

str1 != str2
str2 == str3
str1 == str2
str1 == str4


看看q行l果后,l出我自q理解说明Q?/p>

1、String有一个所谓的String poolQ这是一个什么东西呢Q我理解是它是堆QheapQ上Ҏ的一个空_我叫它特D堆Q。注意它也是在堆上?/p>

2、生Stringcd的对象有两种ҎQ那么这两种Ҏ有什么区别呢Q我的理解是String str = “abc”是先用equalsҎQStringc覆盖了equalsҎQ判断这个特D堆QString poolQ是否有abcQ有则将原来在栈中指向abc的引用赋值给strQ否则就在这个特D堆QString poolQ上创徏一个abc对象。String str2 = new StringQ?abc"Q则是在普通堆上创建abc对象。所以str和str2是指向不同的对象Q它们是不同的?/p>

3、String有个intern()ҎQ这个方法是个本地方法,当用String str2 = new StringQ?abc"Q来创徏对象Ӟ它相当于告诉JVMQ我q个abc对象是放在特D堆QString poolQ上的。所以第三个打印l果是相{的?/p>

4、需要注意的一点:String是finalc,它是恒定c,一旦创建就无法改变Q所以用intern()Ҏ是重新在String pool中创Z一个新的对象?/p>

5、StringcL一个伴随类StringBufferQ需要了解它们之间的区别请google之?/p>

gkc 2009-10-13 11:56 发表评论
]]>
վ֩ģ壺 Ͽ| ͷ| ǧ| | ͬ| Ҷ| ƽ| ̨| | ݳ| ͨ| | | | | ƺ| | | | żҽ| հ| | ï| | | | ɽ| Ͷ| ν| ʼ| | | | Զ| û| | Դ| | | | |