字符串赋值的两种方法
- String s1 = “粪粪”;
- String s2 = new String(“粪粪”);
代码样例:
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
//赋值的两种方式分析:
//String的两种赋值方式,推荐使用第一种赋值方式
//1.直接赋值
String s1="粪粪";
String s3="便便";
String s4="便便";
//2.使用new关键字创建对象,new:表示申请内存空间
String s2 = new String("粪粪");
System.out.println(s1==s2);//false
System.out.println(s1==s3);//false
System.out.println(s4==s3);//true
}
}
分别对上述两种情况进行分析(分析如下图):
从图中可知: 堆内存中有一部分内存给到了字符串常量池,用字符串直接赋值的方法(第一种方法)时,系统会先从字符串常量池中找,是否有“粪粪”这个对象,若是没有,则在字符串常量池中创建一个粪粪对象,反之,不创建,共用一个常量池中的对象。但若是用第二种使用new关键字的方式给字符串赋值,系统也是会从常量池中找是否已经有了“粪粪”这个对象,若没有,则现在常量池中建立一个“粪粪”对象,然后在堆内存中再次创建一个“粪粪”的对象。
总结:用第一种方法给字符串赋值,只会产生一个对象。用第二种方法给字符串赋值,最少会创建一个对象,最多创建两个对象。所以建议使用第一种赋值方式以此节省内存。
第一种赋值方式,编译期和运行期的区别:如果在编译期 值可以被确定,就使用已有对象,否则会创建一个新的对象来接收。
代码样例:
public class pro15 {
public static void main(String[] args) {
//编译器和运行期的4种方式分析:
String a = "a";
String a1 = a+1;
String a2 = "a1";
System.out.println(a1==a2);//false
System.out.println("----------------------------------");
final String b = "b";
String b1 = b+1;
String b2 = "b1";
System.out.println(b1==b2);//true
System.out.println("----------------------------------");
String c = getC();
String c1 = c+1;
String c2 = "c1";
System.out.println(c1==c2);//false
System.out.println("----------------------------------");
final String d = getD();
String d1 = d+1;
String d2 = "d1";
System.out.println(d1==d2);//false
}
public static String getC() {
return "c";
}
public static String getD() {
return "d";
}
}
结果展示:
false
true
false
false
分析:编译器编译时,对语句逐行编译,每行互不相关
①.String a = “a”;
②.String a1 = a+1;
③.String a2 = “a1”;
④.System.out.println(a1==a2);
即:当编译完①时,在对②进行编译时,并不知道 a 变量的内容,换句话说也就不确定在字符串常量池中是否有该对象,所以会重新创建一个对象,放在常量池中。
但如果将①改成 final String a = “a”; 那么在编译期,进行到②时,此时a是常量,能够确定其值,所以结果为true;
但是用final定义一个函数:例如将第一句改为:final String a = getA();在编译期同样无法确定其值,也会重新创建一个对象。