第一道面试题是说出以下程序的输出结果:
public static void main(String[] args) {
String str="123";
String str1=new String("123");
String str2="123";
System.out.println(str==str1);
System.out.println(str==str2);
}
我只当equals对于字符串是内容的比较,但是==又是怎么比较两个字符串对象是否相等的,当时隐约记得==是比较存储地址和内容是否都相当,但str与str2明明是创建了两个内容为“123”的字符串,存储地址应该不一样吧,好后悔以前用到的时候不求甚解,在网上查找资料,通过两位大神的资料得到了答案。
原文地址:http://www.cnblogs.com/dolphin0520/p/3592500.html
原文地址:https://my.oschina.net/Chaos777/blog/309476
通过上面两篇文章我们知道,对于==符号,分为两种情况
当比较的对象是基本数据类型时,==直接比较两者的数值是否相等
当比较的对象是非基本数据类型,比如String这种引用类型,==比较引用对象所在的内存地址是否相同。
上面这道题,str引用了“123”这个字符串,str1使用new关键字,新创建了一个字符串对象,尽管str和str1的内容是相同的,但是引用的内存地址是不同的。
接下来问题又来了,str和str2都是赋值为"123",那么它们两者引用的对象所在的内存空间是一致的嘛,这就涉及到String类型在java的创建和缓存机制了
String是不可变类,因此它是可以被共享的
在编译期间,JVM会把已出现的字符串常量放入字符串缓存池当中(不包括通过变量或者方法才可以得到的字符串,因为这些在运行期间才可以得到),当创建一个String对象,首先查看缓存池中是否有相同的字符串,如果有则指向这个字符串对象的地址处。
因此,上面这道题中str与str2所对应的字符串都是“123”,它们引用的字符串地址也是一样的。
但是String是不可变类,如果将一个字符串变量赋值给两一个字符串,之前的字符串常量还会继续存在于缓存池中,而不会被垃圾回收机制释放,因此过度使用String类型会导致内存泄露的问题出现,这时候我们可以使用StringBuffer和StringBuilder来解决这一问题。
StringBuffer和StringBuilder在操作字符串的时候,是在同一个对象上进行操作的,而且StringBuffer是线程安全的,StringBuilder不是