对于java程序中的字符直接量(即采用字面值方式赋值,型如:String s1 = "aaaa";),JVM会使用一个字串池StringPool来保存它们。当第一次使用某个字符串直接量时,JVM会将它放入字符串池中进行缓存。在一般情况下,字符串池中的字符串对象不会被垃圾回收。当程序再次需要使用该字符串时,无需重新创建一个新的字符串就可以直接让引用变量直接指向字符串中已有的字符串。而使用new操作创建的字符串对象(即型如:String s2 = new String("aaa");)不指向字符串池中的对象,但是可以使用intern方法使其指向字符串池中的对象。
String a = "ab";
String b = "a"+"b";
//这里的"a"、"b"不是变量,是常量,当使用“+”拼接字符串时,会产生新的String对象,而不是对原有的String对象的追加内容。
System.out.println(a==b); //输出结果为true,对于String对象的相等性比较,最好使用equals()方法,而不使用“==”。
String str1 = "java"; //在编译时就知道对象放在常量池里
String str2 = "blog";
String str = str1 + str2;
//str1、str2是变量在运行时刻才能知道,也就是说str1+str2是在堆里创建的
System.out.println(str); //输出结果为javablog
System.out.println(str=="javablog"); //输出结果为false
String str1 = "abc";
String str2 = "abc";
String str3 = "def";
String str4 = "abcdef";
String str5 = "abc" + "def";//在字符串池中能找到“abcdef”对象,故str5 == str4 为true
String str6 = str2 + str3;//在运行时才知道,也就是说str1+str2是在堆里创建的
String str7 = new String("abcdef");//new操作创建的字符串对象不指向字符串池中的对象
String str8 = str7.intern();//使用intern方法使str7指向的对象加入字符串池中
Java运行环境有一个字符串池,由String类维护。执行语句String str="abc"时,首先查看字符串池中是否存在字符串"abc",如果存在则直接将"abc"赋给str,如果不存在则先在字符串池中新建一个字符串"abc",然后再将其赋给str。执行语句String str=new String("abc")时,不管字符串池中是否存在字符串"abc",直接新建一个字符串"abc"(注意:新建的字符串"abc"不是在字符串池中,而是在堆中创建),然后将其付给str。前一语句的效率高,后一语句的效率低,因为新建字符串占用内存空间。String str = new String()创建了一个空字符串,与String str=new String("")相同。
-------------------------------------------------------------------------------------------------------------------
因为字符串池中的字符串对象不会被垃圾回收,所以当某个字符串池中的字符串对象失去引用时,它将变成垃圾,而字符串池又不回收。于是便产生了java内存泄露。示例如下: