【问题标题】:How do String objects work (like immutable objects)?String 对象如何工作(如不可变对象)?
【发布时间】:2010-03-04 19:36:25
【问题描述】:

我有这两种情况:

String s = "aa";
s = s + " aa";
    System.out.println(s);
    //......

效果很好!它打印 aaaa。 但是有一个问题:

String s = "aa";
this.addStringToStatement(s, " aa");
System.out.println(s);
//...
private void addStringToStatement(String statement, Object value) {
    statement += value;
}

它打印:aa。 是什么原因?? 谢谢!

【问题讨论】:

  • 除了实际的问题/问题(Java 不像您所期望的那样通过引用传递),在现实世界中,您通常会使用内置的 String#concat() 方法或 @987654324 @为此。

标签: java


【解决方案1】:

这里有两个问题需要理解。

  1. 字符串追加操作符将创建一个新的不可变字符串对象。表达式s + value 是内存中与s 不同的对象。

  2. 在您的函数addStringToStatement 中,当您执行statement += value; 时,您不会更改变量s 的值,而是将本地指针statement 重新分配给一个新的String 实例。

编辑:修正了常见的菜鸟错误:在 Java 中,传递的是对象引用,而不是对象本身。

【讨论】:

  • 你做得很好,直到最后一句话。所有 Java 参数都是按值传递的。
【解决方案2】:

这是因为在 Java 中,引用是按值传递的。这里当你将 s 和 "aa" 作为两个参数传递时。

在方法语句中,变量(有s 的引用)被改变 指向别的东西,即“aa aa”。注意只传递了语句引用,s 仍然指向“aa”。

因此,当您打印 s 时,您会得到预期的结果 :)

【讨论】:

    【解决方案3】:

    这是因为在 Java 中按值传递是如何工作的,您需要执行以下操作:

    String s = "aa";
    s = this.addStringToStatement(s, " aa");
    System.out.println(s);
    //...
    private string addStringToStatement(String statement, Object value) {
        statement += value;
        return statement;
    }
    

    【讨论】:

    • 在 Java 中没有通过引用传递这样的东西。
    • 哎呀,我的意思是价值。那里有大错别字。感谢您指出@Michael
    • 这是正确的。部分原因是 Java 有时运行缓慢。
    【解决方案4】:

    Java 中的字符串是不可变的。如果你有一个字符串 s="aa",那么你在 JVM 中只有一个对字符串 "aa" 的引用。如果您希望将字符串“aa aa”分配给 s,则只需将“aa aa”(JVM 中的另一个字符串)的引用(地址)分配给 s,“aa”仍潜伏在 JVM 中的某个位置。

    “Java 引用按值传递”这句话有点令人困惑(如果为真)。如果您使用 StringBuilder sb 并将此 StringBuilder 提供给函数,则引用被“复制”但仍指向与 sb 相同的对象:

    public static void main(String[] args) {
        final StringBuilder sb = new StringBuilder();
        f(sb);
        System.out.println(sb);
    }
    
    private static void f(final StringBuilder sb) {
        sb.append("aa aa");
    }
    

    【讨论】:

      【解决方案5】:

      您必须返回“语句”变量。没有“this.*”部分。

      String s = "aa";
      s = addStringToStatement(s, " aa");
      System.out.println(s);
      //...
       private String addStringToStatement(String statement, Object value) {
          statement += value;
          return statement;
      }
      

      【讨论】:

      • 应该是私有String,而不是私有void
      【解决方案6】:

      @Frank Meißner(刚接触这个,还不能回复答案)

      只是为了澄清 String 和 StringBuilder 之间的区别(以防任何阅读此内容的人感到困惑),虽然两者都将它们持有的 CharSequence 存储为 char[],但 String 中的 char[] 不能更改,因此新的 String 具有为每次更改而创建。在 StringBuilder 的情况下,有像 StringBuilder.append(String) 这样的方法可以更改 StringBuilder 的内部 char[],因此如果调用 StringBuilder.append(String),则不必为要更改的 StringBuilder 的内容。

      按照 Frank Meißner 的示例,System.out.println(sb);将打印“aa aa”,因为在 StringBuilder sb 上调用了 append(String) 方法。 final 在这里不会受到伤害,因为 sb 的身份没有改变,只是它的状态。

      【讨论】:

        【解决方案7】:

        += 如果是字符串,则不会修改字符串本身,而是生成新字符串。在您的方法的情况下,您将此新字符串引用设置为局部变量(参数)

        【讨论】:

          【解决方案8】:

          Java 引用是按值传递的。当您将String 传递给一个方法并且它内部发生变化时,它指向不同的String。您可以在附加后返回String,也可以使用StringBuffer 作为参数。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-03-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-05-04
            • 2014-02-20
            相关资源
            最近更新 更多