该用户从未签到
|
java的String是不可变类。为了提高效率,java为String类提供了String池。
1. 当我们使用形如String s = "abc"的代码为字符串赋值时,JVM首先会检查字符串常量池中是否有"abc"这个字符串,如果有就直接将其地址赋给s;若没有,则在Stirng池中创建一个字符串对象“abc”,再将其地址赋给s。
例如:
public static void main(String[] args) { String s1="hello"; String s2="hello"; String s3="he"+"llo"; System.out.println(s1==s2); System.out.println(s2==s3);}上述代码中,执行String s1 = "hello"时JVM在String池中创建了“hello”对象;当执行到String s2="hello"时,因为此时String池中已经有了“hello”,编译器就直接将“hello”的地址赋给s2。因此s1、s2指向了同一个对象,所以输出为true。S3也是同样道理。
是否入池要看情况而定,等号右边如果是常量则入池,非常量则不入池
String s3 = "a" + "b"; //"a"是常量,"b"是常量,常量+常量=常量,所以会入池.
String s4 = s1 + "b"; //s1是变量,"b"是常量,变量+常量!=常量,所以不会入池.
2. 当使用String s=new String("");这种形式赋值时,实际上产生了两个对象。
例如:String s=new String("abc"),此时先是在String常量池中产生了一个“abc”对象,然后new String()又在堆中分配了内存空间,将常量区中的“abc"复制一份给了堆中的String对象。因此这段代码产生了两个对象,一个在常量区、一个在堆区。
public static void main(String[] args) { String s1="hello"; String s2=new String("hello"); System.out.println(s1==s2);}这里s1指向的是常量区中的”hello“,s2指向的是堆中的”hello“,因此输出为false。
3. java.lang.String的intern()方法
一个初始时为空的字符串池,它由类 String 私有地维护。当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。
它遵循对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。
String str1 = "a";String str2 = "bc";String str3 = "a" + "bc";String str4 = str1 + str2;System.out.println(str3 == str4); // falsestr4 = (str1 + str2).intern();System.out.println(str3 == str4); //true
|
|