Java开发中的strings=“Hello”;s=s+“world!”;这两行代码执行后,原始String对象中的内容是否发生了变化?不,因为String被设计成不可变的(immutable)类,所以它所有的对象都是不可变的对象。在这个代码中,S最初指向一个String对象,内容是“Hello”,然后我们+操作S。
那么s指向的对象变了吗?答案是否定的。这时候s不指向原对象,而是指向另一个String对象,里面是“Helloworld!”,原对象仍然存在于内存中,但S的引用变量不再指向它。通过以上描述,我们很容易得出另一个结论,如果字符串经常被修改或不可预测的修改,使用String代表字符串会造成很大的内存费用。
由于String对象建立后不能再改变,所以每个不同的字符串都需要一个String对象来表示。此时,应考虑允许修改Stringbuffer类,而不是生成每个不同字符串的新对象。此外,这两种对象很容易转换。
同时,我们也可以知道,如果我们想使用内容相同的字符串,我们不必每次都使用String。例如,我们应该在结构中初始化String引用变量,并将其设置为初始值。我们应该这样做:
String引用变量初始化。
后者每次都会调用构造器生成性能低、内存成本高的新对象,毫无意义。因为String对象不能改变,所以对于内容相同的字符串,只需要一个String对象来表示。也就是说,多次调用上述构造器创建多个对象,其String类型属性S指向相同的对象。上述结论也基于这样一个事实:对于字符串的常量,如果内容相同,Java认为它们代表相同的String对象。
无论内容是否相同,使用关键字new调用构造器总是创建一个新的对象。至于为什么String类被设计成不可变类,它的目的决定了它。
事实上,不仅仅是String,Java标准库中的许多类别都是不可变的。在开发系统时,我们有时需要设计不可变类来传递一组相关值,这也是对象思想的体现。不可变类有一些优点,比如因为它的对象只读,多线程并发访问不会有问题。当然也有一些缺点,比如每个不同的状态都需要一个对象来代表,可能会造成性能问题。因此,Java标准库还提供了一个可变版本,即Stringbuffer。