加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 教程 > 正文

Java字符串缓冲池详解

发布时间:2021-11-19 13:04:03 所属栏目:教程 来源:互联网
导读:Java的虚拟机在内存中开辟出一块单独的区域,用来存储字符串对象,这块内存区域被称为字符串缓冲池。那个java的字符串缓冲池是如何工作的呢? String a = abc; String b = abc; String c = new String(xyz); 例如上边的代码: String a = abc; 创建字符串的

Java的虚拟机在内存中开辟出一块单独的区域,用来存储字符串对象,这块内存区域被称为字符串缓冲池。那个java的字符串缓冲池是如何工作的呢?
 
 
String a = "abc";
String b = "abc";
String c = new String("xyz");
例如上边的代码:
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";
    这个程序与上边的程序比较相似,我们分比来看一下:
 
    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");
    }
输出结果: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");
    }
输出结果: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");
    }
输出结果: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);  
 
    }
输出结果: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);  
 
    }
输出结果:true
                 true
分析:加上final后day也变成了常量,所以第二句的引用也是指向的字符串缓冲池。
 
附录
java源码中对于String a = new String(”abc”);这种构造方法的实现
 
public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    } 

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读