【问题标题】:Assign and create new String difference分配和创建新的字符串差异
【发布时间】:2013-04-13 09:13:14
【问题描述】:
        String s1 = new String("string");
        String s2 = new String("string");

        String s3 = "string";
        String s4 = "string";

        System.out.println(s1 == s2);      //FALSE
        System.out.println(s2.equals(s1)); //TRUE

        System.out.println(s3 == s4);      //TRUE
        System.out.println(s3.equals(s4)); //TRUE

创建s1s3有什么区别? 请告诉我

在 String 中,我们只有 String 对象,那么为什么它以不同的方式对待这两个对象。 s1 和 s2 具有不同的内存地址,而 s3 和 s4 具有相同的内存地址。 为什么它基于 new 运算符工作?

【问题讨论】:

  • 如果你想让你的概念在 java String 中清晰,请阅读 KathySierra Scjp 6。第6章弦对弦有精彩的解释,没有人能比她解释得更好。如果您想要 pdf,只需通过 nikhilagrawal60@gmail.com 将您的 mailID 给我。如果其他人有兴趣,他们也可以给我发邮件。
  • 谢谢刚刚知道了.....

标签: java string


【解决方案1】:

当定义它们的类被加载时,String 对象在您的 Java 源代码中表示字符串字面量被添加到共享的 String 池中1。这确保了字符串文字的所有“副本”实际上都是同一个对象......即使文字出现在多个类中。这就是为什么s3 == s4true

相比之下,当您new 一个字符串时,会创建一个不同的新字符串对象。这就是为什么s1 == s2false。 (这是new 的基本属性。保证创建并返回一个新对象……如果它正常完成。)

但是,在任何一种情况下,字符串都将具有相同的字符,这就是equals 返回true 的原因。


虽然了解发生了什么很重要,但真正的教训是比较Java字符串的正确方法是使用equals而不是@987654332 @。

如果您想安排使用== 测试您的String 对象是否相等,您可以使用String.intern 方法“实习”它们。但是,您必须始终如一地这样做......而且实习在各个方面都是一个昂贵的过程......所以这通常不是一个好主意。


1 - 实际上,它比这更复杂一些。它们的对象在类加载和第一次使用文字之间的某个时间被添加到池中。精确的时间是未指定的,并且依赖于 JVM 实现。但是,它保证只发生一次,并且在任何应用程序代码看到与文字对应的 String 对象引用之前。

【讨论】:

  • 为什么实习是一个昂贵的过程?
  • 许多因素。 1) 有一个使用内存的哈希表,当您调用intern 时会对其进行探测/更新。 2)必须使用弱引用将每个实习字符串存储在哈希表中。那是额外的内存 + GC 开销。 3)实习字符串存储在(通常有限的)“permgen”空间中。 GC'ing permgen 通常需要一个完整的 GC。
  • 很好的解释。我在某处读到,Java 1.7 字符串不会进入堆的 PermGen 区域?这是真的吗?
  • @AmitG - AFAIK,Java 1.7 处理字符串的方式与以前相同。 JLS 中指定了有关字符串文字的规则。它不依赖于实现。
  • @AmitG - 在 Java 1.8 中,没有 permgen。但这对于字符串字面量的 observable 语义无关紧要……除了(Java 8 之前的)permgen 堆已满的边缘情况。
【解决方案2】:

s1 是一个新的 String 对象,它不属于任何池化实例的一部分。 s3 是来自池的字符串的实例。查找 java 字符串池。看看String上的相关intern()方法。

这个概念并不是 java 独有的。 String interning 支持其他语言。在该相关说明中,池化常用对象遵循flyweight 模式,并且不限于字符串。看看Integer.valueOf()。整数也有自己的常量池。

【讨论】:

    【解决方案3】:

    JVM 具有自动优化功能。除非您专门创建了一个新的String 对象,并且另一个具有相同值的String 对象已经存在,否则JVM 会自动假定一个新对象不是必需的,并且会为您分配一个指向相等的@987654324 的指针@已经存在的对象。

    基本上,当您使用第二个选项时,会发生以下情况:

    第一步

    创建第一个对象没有问题。

    第二步

    在创建第二个对象之前,会检查字符串池的值。 如果该值当前存在,则无需创建新对象。它只是返回对String 对象的引用。

    第三步

    它没有被分配一个新的对象,而是简单地给它一个在步骤 1 中创建的对象的引用。这是为了节省内存。

    【讨论】:

      【解决方案4】:

      发生这种情况是因为new 运算符强制创建一个新的 String 实例,而在第二种情况下,由于 String 是一个不可变类,JVM 为两个变量提供了相同的 String 实例以节省内存.因为其中一个对象不可能发生变化,从而导致第二个对象也发生变化(不可变,还记得吗?),这没关系。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-12-02
        • 2013-09-26
        • 2013-04-15
        • 1970-01-01
        • 1970-01-01
        • 2020-06-27
        • 2015-05-31
        • 1970-01-01
        相关资源
        最近更新 更多