【问题标题】:if string objects are interned then why change in one does not affect other [duplicate]如果字符串对象被实习,那么为什么改变一个不会影响其他[重复]
【发布时间】:2015-05-22 19:14:44
【问题描述】:

如果字符串对象被实习,那么为什么改变一个不会影响另一个

public class EqualExample {
public static void main(String[] args) {

    String str = new String("Hello");
    String str1 = new String("Hello");

    System.out.println(str == str1);
    System.out.println(str1.equals(str));

}

}

上述程序的输出将是

假的 真的

    public class EqualExample {
    public static void main(String[] args) {

    String str = "Hello";
    String str1 = "Hello";

    System.out.println(str == str1);
    System.out.println(str1.equals(str));

}

}

以上代码的输出是

真 真的

这是因为在字符串池中 Heloo 已经存在,所以它在字符串中实习并引用同一个对象,那么为什么如果我将 str1 更改为“heloo java”,那么为什么 str 仍然具有值“heloo”。因为它们引用相同的对象,所以 str 的值必须改变 公共类 EqualExample { 公共静态 void main(String[] args) {

    String str = "Hello";
    String str1 = "Hello";

    System.out.println(str == str1);
    System.out.println(str1.equals(str));

    str1="Heloo java";
    System.out.println(str+str1);
    System.out.println(str == str1);
    System.out.println(str1.equals(str));

}

}

输出真 真的 HelooHeloo java 错误的 假的

【问题讨论】:

  • String 对象是不可变的。您不能更改 String 对象的内容。
  • 答:因为字符串是不可变的,如果你改变字符串的值,它就是不同的字符串。

标签: java


【解决方案1】:

str1 不是字符串。它是对 String 对象的引用。通过做

str1 = "Heloo java";

您没有修改 String 对象,您只是将引用指向另一个不同的 String 对象。

之前:

str --------> "Hello"
                ^
str1 -----------|

之后:

str --------> "Hello"

str1 -------> "Heloo Java"

改变对象将包括做类似的事情

str1.setCharacters("Heloo Java");

但是这样的方法不存在,因为字符串是不可变的。因此它们的字符不能被修改(除非使用肮脏的反射技巧)。

【讨论】:

    【解决方案2】:

    你有两个指针指向内存中的同一个地址。改变一个值意味着重定向一个指针,而另一个保持不变。

    【讨论】:

      【解决方案3】:

      您不能更改现有字符串。字符串是不可变的。当您说“将 str1 更改为 "heloo java"”时,您实际上是在分配对不同不可变对象的引用。

      【讨论】:

        【解决方案4】:
        String str = "Hello"
        

        意思

        if "Hello" exists in the pool,
              then return "Hello" instance reference from pool
        else
            create an object "Hello". Keep the object in the pool, then return reference
        

        但是

        String str = new String("Hello");
        

        意思

        始终创建“Hello”对象,无论它是否存在于池中。

        【讨论】:

          【解决方案5】:

          根据Java Docs,Strings 是不可变的。也就是说:它们不会改变,或者一旦创建:它们永远不会改变(对象的状态,而不是引用变量。)

          但是,您可以更改引用变量,在现有引用变量中创建一个新的 String Object 。如果没有指向“旧”String 对象的引用变量,则“旧”String 对象被您的程序视为不可访问,垃圾收集器可能会清理它。

          在实践中,代码中有注释解释:

              public static void main(String[] args) {
              
              String s1 = "Test 1";
              
              String s2 = s1;
              
              System.out.println("s1: "+s1+ " and s2: "+s2);
              
              s2 = "String 2";
              
              System.out.println("s1: "+s1+ " and s2: "+s2);
              
              //Garbage Collector will not clean the "String 1" because we still have the s1 Reference Variable pointing. 
          
          }
          

          输出:

          s1:测试 1 和 s2:测试 1

          s1:测试 1 和 s2:字符串 2

          正如您所提到的,为了提供更好的性能,如果创建的新 String 与现有的“有意义地相等”(传入 String.equals 方法),JVM 不会在堆中创建新的 String 对象堆中的一个。但是您可以通过引用变量中的new String("test 1") 来强制创建。

          String 的这种不可变状态是为了保证您的程序能够正常工作。想象一下,如果您有两个 String 的引用并且其中一个发生了更改,那会有多危险:另一个也将被更改,并且可能会发生奇怪的事情。

          Java 类也是不可变的;比如包装类:java.lang.Integer, java.lang.Double, ....

          我给大家讲解了垃圾回收器,让你深刻理解Reference Variable与堆中对象的关系。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-05-15
            • 1970-01-01
            • 2018-01-26
            • 1970-01-01
            • 2019-11-02
            • 1970-01-01
            • 2015-05-20
            相关资源
            最近更新 更多