一、String的两种创建方式
1、String str1 = "abc";
①在栈中开辟一块空间创建引用str1;
②字符串池中有“abc”,直接让str指向“abc”;
字符串池中没有“abc”,先创建,然后将str指向 “abc”
2、String str2 = new String("abc");
①在栈中开辟一块空间创建引用str2;
②在堆中创建对象new String("abc");
③str2指向堆中的“abc”
二、对两种创建方式进行一下比较
和字符串“abc”比较
1、String str1 = "abc"
System.out.println(str1 == "abc"); true
str1初始化的时候已经在字符串池中创建了一个“abc”,当执行str1==“abc”的时候不会再次创建,此时str1和字符串“abc”指向的是字符串池中的同一个地址,所以输出为true
2、String str2 = new String("abc");
System.out.println(str2 == "abc"); false
str2指向的是堆中“abc”的地址,而字符串“abc”再常量池中,所以为false。
因此不难得出,System.out.println(str2 == str1) ;false
多次创建
1、String str1 = "abc"
String str2 = "abc";
System.out.println(str1==str2); true
2、String str1 = new String("abc");
String str2 = new String(abc);
System.out.println(str1==str2); false
总结:第一种方式,只是创建了多个引用,单只有一个对象,比较节省内存空间,会在一定程度上提供程序的运行;
第二种方式,会创建多个引用,多个对象,加重了程序的负担。
三、字符串的拼接
1、String str1 = "abcd";
String str2 = "ab"+"cd";
System.out.println( str1==str2 ); true
当一个字符串是由多个字符串常量拼接而成时,它自己肯定也是字符串常量,因此str1初始化之后,字符串池中已存在“abcd”,因此由“ab”和“cd”拼接而成的str2不会再重复创建。
2、String str1 = "abcd";
String str2 = new String("abcd");
String str3 = "ab" + new String("cd");
System.out.println( str1==str2 ); false
System.out.println( str1==str3 ); false
System.out.println( str2==str3 ); false
str1 == str2 输出为false,文章的前半部分已经讲过了,这里就不再赘述了;
str3 是由字符串常量“ab” 和new String("cd")拼接而成的,这里new String("cd")是又创建了一个新的对象,因此,str1 == str3 和 str2 == str3 均输出为false;
3、String str1 = "ab";
String str2 = "a";
final String str3 = "a";
String str4 = str2+"b";
String str5 = str3 +"b";
System.out.println((str1 == str4)); false;
System.out.println((str1 == str5)); true;
①使用包含变量的字符串链接,如:str2+"b",创建的对象是运行期才创建的;
只要str2是变量,无论str2指向的池中的字符串就还是堆中的字符串对象,运行期str2+"b"操作实际上是编译器创建了StringBuilder对象进行了append操作后通过toString()返回了一个字符串对象存在堆中。 所以,(str1 == str4) 为false
②str3 是一个用final修饰的变量,再编译期已知,再运行时会直接用常量“a” 代替str3
因此 str3+"b " 就等效于 “a” + "b" ,所以,(str1 == str5) 为true.