是什么让 String 不可变?

What makes String immutable?

我知道字符串是不可变的,但为什么呢?

哪个概念使字符串 class 不可变?

public class Mainclass
{
    public static void main(String[] args) 
    {
        String s = "Example";
        s.toUpperCase();
        System.out.println(s);
    }
}

结果:

Example

任何 class 不能被子class编辑并且不提供任何修改其状态的方法——例如通过不提供任何设置器、将其字段保持私有等——是不可变的。没有什么特别的魔法。

String 是不可变的,因为无法更改其内部表示的内容,无法获得对其内部表示的引用,也无法对其进行子类化。这意味着无论您对 String 做什么,都无法更改其内容。

toUpperCase()这样的方法实际上做的是return一个新字符串,它与旧字符串具有相同的内容。但是,新的 String 是一个单独的对象。对初始字符串的引用现在不会指向新字符串。

如果您想打印出 toUpperCase() 的结果,请按以下方式进行操作:

String s="Example";
String upperCase = s.toUpperCase();
System.out.println(upperCase);

编辑:引用与对象

Java 中的变量是对对象的引用。 recerence 本质上是一个指示 Java "your object is here" 的指针,指向某个内存位置。但是引用和对象不是一回事。让我们看下面的例子

String s = "Test";
String a = s;
String s = "another test"

我在这里所做的是声明一个名为 s 的引用,并将其指针设置为一个新创建的对象 - 在本例中是一个值为 "Test" 的字符串。然后我声明另一个引用 a 并将其设置为引用 s 引用的同一个对象。请注意,有两个引用但只有一个对象。

从那里我将引用 s 更改为指向不同的对象 - 在本例中为值为 "another test" 的字符串。这将创建一个新对象,尽管引用被重用。但是,引用 a 仍然指向原始对象,该对象保持不变。如果我们做 println(a) 它仍然会打印 "Test"。这是因为对象本身是不可变的。任何指向它的东西都会 return 相同的值。我可以将引用指向其他地方,但不能更改对象。

将变量想象成 phone 书中的条目。如果我为某人输入一个条目并说他的姓氏是 "BOB",然后有人出现并将其划掉并写为 "ALICE",这不会突然改变 Bob 的性别或他的名字。 BOB 不会自发地变成 ALICE,因为有人重写了我的 phone 书。它只是改变了我 phone 书中的价值,而不是实际的人。我希望这个比喻有所帮助。

这些是您可以使任何 type/class 不可变的步骤

1) 不要提供“setter”方法——修改字段或字段引用的对象的方法。

2) 将所有字段设为最终字段和私有字段。

3) 不允许成为 sub class,使 class 最终。

4) 具有可变实例变量时要特别注意。

其中一个原因是安全性。网络连接的参数是字符串类型。应该不容易修改。