【问题标题】:Aren't String objects in Java immutable? [duplicate]Java中的String对象不是不可变的吗? [复制]
【发布时间】:2011-03-24 19:26:50
【问题描述】:
String s = ...;

s = s.substring(1);

这可能吗?我以为你不能在 Java 中更改 String 对象。

【问题讨论】:

  • 如果只有s.substring(1) 会更改s 中的字符串,那么您将是正确的。但是您正在为s 分配一个新字符串。
  • 您只是在更改引用,而不是原始字符串本身。一个次要的风格点 - 创建一个新的、描述性命名的局部变量通常比重复使用这样的变量更好。
  • 不要将对象与引用混淆。对象可能是可变的或不可变的。引用可能是final 或不是。引用final 不会使对象不可变。不可变对象可以通过引用来引用,而引用不必是 final
  • Brandon 你应该先了解什么是引用,什么是可变性。

标签: java string immutability


【解决方案1】:

字符串对象是不可变的。然而,字符串 references 是可变的。以上,s 是一个参考。

【讨论】:

  • +1 简短而正确。 s 的初始值仍然存在,未更改并且可能现在未引用,在内存中 - 等待获得 GC'd。然而,引用 s 现在指向一个新的、同样不可变的对象,由 substring 方法创建。
  • 当,我希望我在你之前看到这个 Q 让自己获得一堆简单的代表。 :) +1
【解决方案2】:

String 对象是不可变的,这意味着s 引用的instance 的值不能改变。

您的代码不会改变实例。
相反,它将s 引用更改为引用一个新的字符串实例。

例如:

String a = "1";
String b = a;
a = "2";

执行这段代码后,b 仍然是"1"
b = a 行将b 设置为引用a 当前引用的同一"1" 实例。
当您随后编写 a = "2" 时,您正在更改 a 变量以引用不同的 ("2") 实例。
但是,b 仍然引用的原始 "1" 实例并没有改变。

【讨论】:

    【解决方案3】:

    是的,String 对象是不可变的。

    变量s是一个对象的引用,引用本身可以改变它所指向的对象——重新分配引用并不影响它所指向的对象。

    String.substring 方法实际上是返回 String 的新实例,因此原始的 String 对象保持不变。

    下面是一个简单的例子,说明原来的String没有被substring方法改变::

    String s = "Hello!";
    s.substring(1);
    
    System.out.println(s);   // Prints "Hello!"
    

    上面的例子将打印“Hello!”因为substring 方法将返回一个新的String 而不会影响原来的String。原始String 不可更改,因为它是不可变的。

    将以上内容与以下内容进行比较:

    String s = "Hello!";
    s = s.substring(1);
    
    System.out.println(s);   // Prints "ello!"
    

    在这个例子中,对s的引用变成了substring方法返回的String,所以当与s关联的String被`System.out.println"打印出来时,输出的字符串将是“hello!”

    【讨论】:

      【解决方案4】:

      在这里,您正在创建一个新字符串并将其分配给预先使用的引用。 s 引用的原始字符串是垃圾收集的。实际上没有改变任何字符串。

      【讨论】:

        【解决方案5】:

        //创建对字符串“Hello”的引用s

        String s = "Hello";

        //现在打印s引用的字符串的子字符串

        System.out.println(s.subString(1));

        //现在打印s引用的字符串

        System.out.println(s);

        上面的代码 sn-p 会首先打印 H,然后在 第二 行它会打印 Hello现在为什么要先打印 H? : 事情是subString() 方法返回一个字符串 *不改变引用s 引用的字符串*。 s 仍然指的是“你好”。现在,当您尝试打印 s 时,它将打印 s 所指的字符串。这样 String "Hello" 是不可变的。你只能用它来产生另一个字符串,但你不能改变它。

        当使用语句 s = s.subString(1); 您所做的是 s 现在指的是“Hello”的 subString(),但“Hello”本身仍未修改。

        【讨论】:

          【解决方案6】:

          所以:

          String foo = "foo";
          foo.substring(1);
          System.out.println(foo);
          
          //of course..
          foo = "aa";
          System.out.println(foo);
          

          【讨论】:

            【解决方案7】:

            当您使用 String s = "abc" 时,您会创建对具有不可变值 "abc" 的 String 对象的 String 引用。

            然后,当您说 s = s.substring(1); 时,您将 s 分配给一个新创建的包含“bc”的 String 对象 - 但原始对象没有改变。

            这是一个常见的错误原因,因为如果你没有赋值,你可能会得到意想不到的结果。

            许多 Java 新手开发人员会使用 trim() 之类的方法,但没有意识到 trim() 不会影响 String。

            s.trim()

            s = s.trim()

            【讨论】:

              【解决方案8】:

              测试一下:

              String s = "Test";
              String j = s;
              
              s = s.substring(1);
              

              s 现在是 Tj 仍然是 Test

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-04-18
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多