Java中String的==比较,生成对象个数
“==”作用于字符串是比较地址是否相同!!比较字符串的值是否相同需要使用equals()方法。
1 常量池和堆上的字符串
String str1 = "abcd";
String str2 = "abcd";
String str3 = new String("abcd");
String str4 = new String("abcd");
String str5 = new StringBuilder("ab").append("cd").toString();
System.out.println(str1 == str2); // true
System.out.println(str1 == str3); // false
System.out.println(str1 == str4); // false
System.out.println(str3 == str5); // false
str1==str2 :true,这是因为String str1 = “abcd”这种方式是生成了一个指向常量池中“abcd”对象的引用,若常量池中没有“abcd”,则会新建一个,字符串str1和str2都是指向常量池中“abcd”对象的引用,这个过程只在常量池中新建了一个对象,因此相等。而str3,str4是在堆内存中各自新建了一个String对象,因此输出false。至于会不会在常量池中创建对象,要看常量池中存不存在“abcd”,示例中是存在的,如不存在,则会在常量池中创建一个“abcd”对象,堆中的String对象的成员value会指向常量池中的对象。画个图:
至于str5是调用StringBuilder的toString方法返回new String(value, 0, count)实现的,同样输出false,但是要注意的是,str5的value不指向常量池的“abcd”对象,这是指向StringBuilder的成员变量value,同样若常量池不存在“abcd”对象,也不会去常量区创建。
2 字符串拼接
String str1 = "abcd";
String str2 = "a" + "b" + "c" + "d";
String str3 = "ab" + "cd";
String tmp1 = "ab";
String tmp2 = "cd";
final String tmp3 = "ab";
String str4 = tmp1 + tmp2;
String str5 = tmp1 + "cd";
String str6 = tmp3 + "cd";
String str7 = tmp1 + tmp2;
System.out.println(str1 == str2); // true-(1)
System.out.println(str1 == str3); // true-(2)
System.out.println(str1 == str4); // false-(3)
System.out.println(str1 == str5); // false-(4)
System.out.println(str1 == str6); // true-(5)
System.out.println(str4 == str7); // false-(6)
str2和str3这种字符串连接在虚拟机进行编译时会进行优化,直接将其编译成这些常量相连的结果,指向常量池中的对象,而不是在运行时进行“+”计算,因此(1)(2)为true。
str4、str5、str7这种有变量的连接方式,实际上是通过StringBuilder完成的,以str4为例:
StringBuilder strB = new StringBuilder();
strB.append(tmp1);
StrB.append(tmp2);
// 如果有更多的连接,继续append
String str4 = strB.toString();
这个过程产生一个StringBuilder对象,StringBuilder继承了AbstractStringBuilder,AbstractStringBuilder中有成员char[] value,最后调用了StringBuilder的toString方法,其返回一个String对象,所以其过程产生3个对象,但是只有一个String对象。str4、str5、str7各自指向堆中不同的String对象,虽然值相同,但是地址不同,所以(3)(4)(6)为false。
// StringBuilder的构造函数
public StringBuilder(int capacity) {
super(capacity);
}
// 其调用父类的构造函数
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
// StringBuilder的toString方法
@Override
public String toString() {
return new String(value, 0, count);
}
但是为什么同样是有变量的连接方式,为什么str1 == str6输出true,这里是因为final变量和普通变量的区别,当final修饰基本数据类型或String变量时,如果编辑期间能够知道它的确切值,编译器会把它当作常量使用,也就是说,用到该final变量的时候,相当于直接访问这个常量,不需要在运行时确定,所以str6和str2、str3一样,在编译时就完成了连接,(5)为true。如果在编译时无法获取到确切值,同样会通过StringBuilder进行连接,则输出false。
final String tmp3 ;
tmp3 = "cd";
String str6 = tmp3 + "cd";
System.out.println(str1 == str6); // false
上一篇: 批量生成对象
下一篇: 图片懒加载 在可视区域才加载