1. == 和 equals()
public class App {
public static void main(String[] args) {
String s1 = "Hello";
String s2 = "Hello";
String s3 = s2;
System.out.println(s1 == s2); // true
System.out.println(s2 == s3); // true
//
String s4 = new String("Hello");
String s5 = new String("Hello");
System.out.println(s4 == s5); // false
System.out.println(s4.equals(s5)); // false
}
}
解析:先看第3句代码
:"Hello"是字符串字面常量, 也是一个String类型的对象, Java编译器在常量池中分配空间并存储字符序列, 然后将该对象的引用赋值给变量str1;再看第4句代码
, "Hello"是字符串字面常量, Java编译器发现在常量池中已经存在该对象, 于是直接将该对象的引用赋值给变量str2, 换句换说, 编译器会把在程序中出现的相同内容的字符串字面量视作为同一个String对象。
最后的str4和str5是在堆上开辟的空间,str4和str5指向的是不同的对象。
==运算符用于比较两个引用类型的变量时, 比较的是它们的引用值是否相等。
可以理解为引用的对象的地址是否相等,就上述来说,s1,s2,s3都指向对象"Hello",所以它们互等。但是对于s4和s5,它们分别指向不同的对象,两个这两个对象的地址不同,所以最终s4和s5不相等。尽管s4和s5从内存角度上来看不相等,但是s4和s5字符串的内容都是"Hello",所以s4.equals(s5)是true。
Java中,没法获取对象的地址,这要是在C++中,可以通过&取地址符来清晰的观察各个对象的内存地址。当然,Java中的String在内存和C++中std::string内存上的设计还是不同的。
// 看以下C++代码, 实际上 text1和text2的内存地址并不一样。
std::string text1 = "xxx";
std::string text2 = "xxx";
qDebug() << &text1;
qDebug() << &text2;
2. 从C++内存角度来看Java中的String
String 类是不可改变的,所以一旦创建了 String 对象,那它的值就无法改变了
。该怎么理解这句话???
public class App {
public static void main(String[] args) {
String str = "Hello";
System.out.println(str);
str = "World";
System.out.println(str);
}
}
从结果上看是改变了,但为什么说 String 对象是不可变的呢?
原因在于实例中的 str 只是一个 String 对象的引用,并不是对象本身,当执行 str = "World"; 创建了一个新的对象 "World",而原来的 "Hello" 还存在于内存中
。
但是我们从C++的角度来看,完全又不一样了。
std::string text1 = "xxx";
std::cout << &text1 << " " << * &text1 << std::endl;
text1 = "aaa";
std::cout << &text1 << " " << * &text1 << std::endl;
两次都是指向同一块内存空间,只不过是内存中值的改变罢了。原来的Hello被新值World给覆盖了而已。
3. StringBuffer 和 StringBuilder
// 这里并不是修改了str所指向的对象的内容, 而是改变了str变量的引用值,
// 让它指向了新的字符串对象"World".
String str = "Hello";
str = "World";
(1) StringBuffer
:根据之前描述知道,如果想创建一个内容改变的字符串对象,那么String类显然是不满足要求的,这是可以考虑StringBuffer和StringBuilde两个类。StringBuffer是线程安全的,其内部使用了同步机制,导致在调用方法时,频繁地加锁和解锁,影响了执行效率。
(2)StringBuilder
:非线程安全。如果不存在线程安全的问题,那么使用StringBuilder可以提高字符串的访问效率。
(3) 基本使用原则
:
如果要操作少量的数据用 String ;
单线程操作大量数据用StringBuilder ;
多线程操作大量数据,用StringBuffer。