java字符串缓冲池分析

来源:互联网 发布:南风知我意林如斯txt 编辑:程序博客网 时间:2024/06/05 21:11

    java的虚拟机在内存中开辟出一块单独的区域,用来存储字符串对象,这块内存区域被称为字符串缓冲池。那个java的字符串缓冲池是如何工作的呢?

String a = "abc";String b = "abc";String c = new String("xyz");
  • 1
  • 2
  • 3

例如上边的代码: 
String a = “abc”;

    创建字符串的时候先查找字符串缓冲池中有没有相同的对象,如果有相同的对象就直接返回该对象的引用,如果没有相同的对象就在字符串缓冲池中创建该对象,然后将该对象的应用返回。对于这一步而言,缓冲池中没有abc这个字符串对象,所以首先创建一个字符串对象,然后将对象引用返回给a。

String b = “abc”;

    这一句也是想要创建一个对象引用变量b使其指向abc这一对象。这时,首先查找字符串缓冲池,发现abc这个对象已经有了,这时就直接将这个对象的引用返回给b,此时a和b就共用了一个对象abc,不过不用担心,a改变了字符串而影响了b,因为字符串都是常量,一旦创建就没办法修改了,除非创建一个新的对象。

String c = new String(“xyz”);(这种构造方法的实现见附录)

    查找字符串缓冲池发现没有xyz这个字符串对象,于是就在字符串缓冲池中创建了一个zyx对象,然后再将引用返回。

    从上边的分析可以看出,当new一个字符串时并不一定是创建了一个新的对象,有可能是与别的引用变量共同使用了同一个对象。下面看几个常见的有关字符串缓冲池的问题。

到底创建了几个字符串对象

        String a = "abc";        String b = "abc";        String c = new String("xyz");        String d = new String("xyz");        String e="ab"+"cd";
  • 1
  • 2
  • 3
  • 4
  • 5

    这个程序与上边的程序比较相似,我们分比来看一下:

    String a = “abc”;这一句由于缓冲池中没有abc这个字符串对象,所以会创建一个对象;String b = “abc”;由于缓冲池中已经有了abc这个对象,所以不会再创建新的对象;String c = new String(“xyz”);由于没有xyz这个字符串对象,所以会首先创建一个xyz的对象,然后这个字符串对象又作为String的构造方法,在内存中(不是缓冲池中)又创建了一个新的字符串对象,所以一共创建了两个对象;String d = new String(“xyz”);省略了创建一个对象的过程,所以只创建了一个对象;String e=”ab”+”cd”;由于常量的值在编译的时候就被确定了。所以这一句等价于String e=”abcd”;创建了一个对象

    所以创建的对象的个数分别是:1,0,2,1,1

到底相等不相等

    我们在学习java时就知道两个字符串对象相等的判断要用equal而不能使用==,但是学习了字符串缓冲池以后,应该知道为什么不能用==,什么情况下==和equal是等价的,首先,必须知道的是,==比较的是两个对象的内存地址是否相等,下面我们就通过几个程序来看一下:

public static void main(String[] args) {         String s1 = "Monday";         String s2 = "Monday";         if (s1 == s2)             System.out.println("s1 == s2");         else             System.out.println("s1 != s2");     }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

输出结果:s1 == s2 
分析:通过上边的介绍字符串缓冲池,我们知道s1和s2都是指向字符串缓冲池中的同一个对象,所以内存地址是一样的,所以用==可以判断两个字符串是否相等。

public static void main(String[] args) {         String s1 = "Monday";         String s2 = new String("Monday");         if (s1 == s2)             System.out.println("s1 == s2");         else             System.out.println("s1 != s2");         if (s1.equals(s2))             System.out.println("s1 equals s2");         else             System.out.println("s1 not equals s2");     } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

输出结果:s1 != s2 
                 s1 equals s2 
分析:由上边的分析我们知道,String s2 = new String(“Monday”);这一句话没有在字符串缓冲池中创建新的对象,但是会在内存的其他位置创建一个新的对象,所以s1是指向字符串缓冲池的,s2是指向内存的其他位置,两者的内存地址不同的。

public static void main(String[] args) {         String s1 = "Monday";         String s2 = new String("Monday");         s2 = s2.intern();         if (s1 == s2)             System.out.println("s1 == s2");         else             System.out.println("s1 != s2");         if (s1.equals(s2))             System.out.println("s1 equals s2");         else             System.out.println("s1 not equals s2");     }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

输出结果:s1 == s2 
                 s1 equals s2 
分析:先来说说intern()这个方法的作用吧,这个方法的作用是返回在字符串缓冲池中的对象的引用,所以s2指向的也是字符串缓冲池中的地址,和s1是相等的。

public static void main(String[] args) {         String Monday = "Monday";          String Mon = "Mon";          String  day = "day";          System.out.println(Monday == "Mon" + "day");          System.out.println(Monday == "Mon" + day);      }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

输出结果:true 
                 false 
分析:第一个为什么等于true我们已经说过了,因为两者都是常量所以在编译阶段就已经能确定了,在第二个中,day是一个变量,所以不能提前确定他的值,所以两者不相等,从这个例子我们可以看出,只有+连接的两边都是字符串常量时,引用才会指向字符串缓冲池,否则都是指向内存中的其他地址。

public static void main(String[] args) {         String Monday = "Monday";          String Mon = "Mon";          final String  day = "day";          System.out.println(Monday == "Mon" + "day");          System.out.println(Monday == "Mon" + day);      }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

输出结果:true 
                 true 
分析:加上final后day也变成了常量,所以第二句的引用也是指向的字符串缓冲池。

附录 
java源码中对于String a = new String(”abc”);这种构造方法的实现

public String(String original) {        this.value = original.value;        this.hash = original.hash;    }
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 足球点球 皇马点球胜阿森纳 点球大战规则 武磊造点球算助攻吗 点球是什么意思 点球可以补射吗 足球点球技巧 足球点球大战 篮球点球规则 萨里var点球判罚 足球点球规则 那不勒斯点球 足球赛 卡洛斯禁止踢点球 用脸挡住五个点球 罗伯特巴乔射失点球 点痣恢复 点痣是什么 点痣后图片 点痣疼吗 点痣痛不痛 点痣痛吗 合肥点痣 点痣疼不疼 专业点痣 点痣堂 点痣的费用 哪里点痣好 三亚点痣 海口点痣 去哪里点痣 点痣哪里有 南昌点痣 点痣的药 点痣价位 点痣的医院 点痣了 点痣哪里好 汕头点痣 药物点痣1到7天图 点痣恢复过程图