【问题标题】:How do Java strings work [duplicate]Java字符串如何工作[重复]
【发布时间】:2013-05-02 04:47:21
【问题描述】:

我试图准确地理解 Java 字符串是如何不可变的。我知道这应该是一个简单的概念,但是在阅读了几个在线网页后,我仍然不太明白。

我不明白 Java 字符串是如何“不可变”的。我目前有以下代码:

public static void main(String[] args) {

  String name = "Jacob Perkins";

  System.out.println( name );

  name = name + "!";

  System.out.println( name );

}

我的输出如下:

Jacob Perkins
Jacob Perkins!

如果字符串应该是不可变的,为什么会发生这种情况?为什么我可以为字符串重新赋值?

【问题讨论】:

  • String 变量 不是不可变的(因为它们不同!)您创建了一个新字符串并将其引用分配给变量name
  • 我还是不明白。为什么我会在 Java 字符串中看到术语“不可变”?
  • @user2301187:两个变量可以指向同一个字符串对象。如果字符串是可变的,则可以通过另一个变量的引用看到一个变量对字符串的更改。因为它们不是,所以每个变量都知道它指向的字符串不能“在不查看时更改”。这样做是因为可变字符串会很吓人并增加很多复杂性,例如每当您想要一个不会更改的字符串副本时,您必须记住创建一个字符串副本,否则以后会发生奇怪的事情,也可能是不安全的事情!
  • 但看起来name = name + "!" 正在更改原始名称变量的值。我还是不明白。
  • @user2301187 我已经发布了一个解释它的答案

标签: java string immutability


【解决方案1】:

String 对象是不可变的,只有变量引用发生变化。

在您的示例中,“Jacob Perkins”对象仍然存在,并且有一个新对象“Jacob Perkins!”被创建。

name 变量指向新对象。

【讨论】:

    【解决方案2】:

    实际发生的是创建了 3 个 String 对象。 “雅各布·帕金斯”、“!”和“雅各布·帕金斯!”。您并没有真正修改“Jacob Perkins”实例。您刚刚将 name 变量的引用从“Jacob Perkins”实例更改为“Jacob Perkins!”。

    【讨论】:

    • 我不明白您所说的“更改名称变量的引用”是什么意思。
    • 在第一个 println() 中,name 变量指向“Jacob Perkins”字符串对象。该对象并没有真正改变,因为字符串是不可变的。相反,创建了另外两个新的字符串对象,“!”和“雅各布·帕金斯!”。然后 name 变量指向“Jacob Perkins!”。您实际上创建了 3 个 String 对象,没有一个被静音。
    【解决方案3】:
    String name = "Jacob Perkins";
    
    String name2 = name + "!";
    name.substring(5); // or wather syntax is
    

    那些不会改变变量名的

    【讨论】:

      【解决方案4】:

      字符串本身一旦创建,就永远无法更改。您的代码示例所做的是将 name 中的字符串替换new 字符串,该字符串由 name 和一个感叹号。 (name的原始内容,不再被任何变量引用,最终会被垃圾回收器回收。)

      如果您要检查编译后的代码(或使用调试器单步调试),您会发现您的 name + "!" 表达式已被编译为 StringBuilder 对象的创建和对该对象的一些操作。

      也就是说,strings 是不可变的,但 variable name 不是。它的值发生变化,指向不同的字符串。字符串本身永远不会改变。

      【讨论】:

        【解决方案5】:

        让一张图片为你解释一下:

        在左侧,您有变量,实际上是一个引用

        1. String name = "Jacob Perkins;" 字符串“Jacob Perkins”已创建,name 指向它。
        2. name = name + "!"; 新字符串“Jakob Perkins!”已创建,并且引用现在指向新的字符串。但是,旧的保持不变,因为 String 是不可变的。

        【讨论】:

          【解决方案6】:

          在 Java 中有引用,也有值。

          当你说

          String foo = "John Smith";

          foo 是一个变量,持有一个引用。引用指向包含“John Smith”的对象或值。

          变量持有的引用是可变的。我可以这样做:

          foo = "Jack Smith";

          而且我已经改变了引用。但是,如果我这样写代码:

          String foo = "John Smith";
          String bar = foo; //bar's reference is a copy of foo's reference - the same value
          foo = "Jack Smith";
          System.out.println(bar); //prints John Smith
          

          我们看到,即使我们改变了 foo,bar 并没有改变。为什么?简单地说,当我们写foo = "Jack Smith"; 时,我们让 foo 指向一个新的字符串。我们没有通过 foo 来修改字符串,因为 Java 中没有方法可以改变,或者可以改变字符串。 而是返回一个新的字符串,并且使变量指向新的,也是不可变的字符串。这样,字符串变量“指向”的对象永远不能被任何东西修改,只能通过该变量。这是它所保证的 Java 语言的一个重要属性。

          【讨论】:

            【解决方案7】:

            也许这会帮助你理解。

            假设您有一个类 Point (java.awt.Point)。 假设您有一个实例 p:

            Point p = new Point(0,0);
            

            然后你创建一个新变量 y 引用相同的对象 p:

            Point y = p;
            

            如果你改变了 p 的值,你也改变了 y。因为 Point 类是可变的。

            p.setLocation(1,1);
            

            它也让 y 引用位置 1,1。

            使用 String 类不会发生。

            String a = "123";
            String b = a;
            

            如果你做 a = a + "4"; a 的新值为“1234”,但 b 仍为“123”;

            他们引用的对象没有改变,只是a现在指向另一个对象。

            【讨论】:

              猜你喜欢
              • 2014-01-29
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-01-28
              • 2011-12-17
              • 1970-01-01
              • 1970-01-01
              • 2016-12-21
              相关资源
              最近更新 更多