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会指向常量池中的对象。画个图:

value
value
str1
常量池-abcd对象
str2
str3
堆-abcd对象1
str4
堆-abcd对象2

至于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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值