【问题标题】:How are Strings created and stored in Java?Java中如何创建和存储字符串?
【发布时间】:2015-06-14 08:56:38
【问题描述】:

为了了解如何创建和存储 String 对象,我尝试了以下程序,并看到了我查询的输出。有人可以帮忙吗?

package corejava.immutable;

public class StringTester {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        String s1 = "Omkar Patkar";
        String s2 = "Omkar Patkar";
        String s3 = "Omkar" + " Patkar";
        String s4 = "Omkar";
        String s5 = s4 +" Patkar";
        String s6 = new String("Omkar Patkar");

        System.out.println("Hashcode s1 = "+s1.hashCode());
        System.out.println("Hashcode s2 = "+s2.hashCode());
        System.out.println("Hashcode s3 = "+s3.hashCode());
        System.out.println("Hashcode s4 = "+s4.hashCode());
        System.out.println("Hashcode s5 = "+s5.hashCode());
        System.out.println("Hashcode s6 = "+s6.hashCode());

        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

        System.out.println("Indentity Hashcode s1 = "+System.identityHashCode(s1));
        System.out.println("Indentity Hashcode s2 = "+System.identityHashCode(s2));
        System.out.println("Indentity Hashcode s3 = "+System.identityHashCode(s3));
        System.out.println("Indentity Hashcode s4 = "+System.identityHashCode(s4));
        System.out.println("Indentity Hashcode s5 = "+System.identityHashCode(s5));
        System.out.println("Indentity Hashcode s6 = "+System.identityHashCode(s6));
        System.out.println("Indentity Hashcode intern s6 = "+System.identityHashCode(s6.intern()));

        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

        System.out.println("s1 == s2 : - "+(s1 == s2));
        System.out.println("s1 == s3 : - "+(s1 == s3));
        System.out.println("s1 == s4 : - "+(s1 == s4));
        System.out.println("s1 == s5 : - "+(s1 == s5));
        System.out.println("s1 == s6 : - "+(s1 == s6));

        System.out.println("\ns2 == s3 : - "+(s2 == s3));
        System.out.println("s2 == s4 : - "+(s2 == s4));
        System.out.println("s2 == s5 : - "+(s2 == s5));
        System.out.println("s2 == s6 : - "+(s2 == s6));

        System.out.println("\ns3 == s4 : - "+(s3 == s4));
        System.out.println("s3 == s5 : - "+(s3 == s5));
        System.out.println("s3 == s6 : - "+(s3 == s6));

        System.out.println("\ns4 == s5 : - "+(s4 == s5));
        System.out.println("s4 == s6 : - "+(s4 == s6));

        System.out.println("\ns5 == s6 : - "+(s5 == s6));

        System.out.println("\ns1 == s6.intern() : - "+(s1 == s6.intern()));
        System.out.println("s2 == s6.intern() : - "+(s2 == s6.intern()));
        System.out.println("s3 == s6.intern() : - "+(s3 == s6.intern()));
        System.out.println("s4 == s6.intern() : - "+(s4 == s6.intern()));
        System.out.println("s5 == s6.intern() : - "+(s5 == s6.intern()));


    }

}

我会看到以下输出:-

Hashcode s1 = 2062602683
Hashcode s2 = 2062602683
Hashcode s3 = 2062602683
Hashcode s4 = 76311326
Hashcode s5 = 2062602683
Hashcode s6 = 2062602683
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Indentity Hashcode s1 = 4337374
Indentity Hashcode s2 = 4337374
Indentity Hashcode s3 = 4337374
Indentity Hashcode s4 = 18019860
Indentity Hashcode s5 = 31054905
Indentity Hashcode s6 = 605645
Indentity Hashcode intern s6 = 4337374
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
s1 == s2 : - true
s1 == s3 : - true
s1 == s4 : - false
s1 == s5 : - false
s1 == s6 : - false

s2 == s3 : - true
s2 == s4 : - false
s2 == s5 : - false
s2 == s6 : - false

s3 == s4 : - false
s3 == s5 : - false
s3 == s6 : - false

s4 == s5 : - false
s4 == s6 : - false

s5 == s6 : - false

s1 == s6.intern() : - true
s2 == s6.intern() : - true
s3 == s6.intern() : - true
s4 == s6.intern() : - false
s5 == s6.intern() : - false

s5、s6的身份hashcode和s1、s2、s3不一样……为什么会这样?

这些对象是在哪个内存区域创建的? ...对象图将有助于理解 ...

【问题讨论】:

  • 所有字符串之间都应该有一个空格......所以它们的最终值应该是“Omkar Patkar”......s5和s6将包含像s1,s2和s3这样的空格...... . 但它们的身份哈希码与 s1、s2 和 s3 不同...为什么不同?
  • 有很多关于字符串的问题,它们是如何创建和存储的,包括字符串池。您是否搜索并阅读过它们?
  • Tom ...抱歉,我看到了很多关于这个话题的链接......我很抱歉。下次我会注意的。

标签: java string memory-management immutability hashcode


【解决方案1】:

您已经创建了字符串字面量和字符串对象。像 s1 和 s2 这样的字符串字面量存储在字符串池中。因为它们是相同的字符串,所以它们具有相同的引用。这是有效的。

使用new 关键字创建的字符串对象会生成一个存储在堆上的对象。它们的处理方式与任何其他对象相同。创建 2 个具有相同字符串值的对象将产生 2 个对象,每个对象都有自己的引用。使用 new 与字符串池中的字符串文字的效率不同。实习 String 对象会将其移至字符串池。

当您使用== 比较两个对象时,您正在比较它们的引用。因此,比较具有相同值的 2 个字符串文字将导致测试为真。但是,测试使用 new 关键字创建的 2 个对象不会。这就是为什么您应该使用equals 方法来比较对象。

编辑

由 2 个字符串字面量的串联创建的字符串将产生一个字符串字面量,例如 s3。因此,s3 与 s1 和 s2 具有相同的身份哈希码。但是,s5 是从一个字符串文字和一个对字符串文字的 reference 创建的,从而产生一个新对象。这就解释了为什么它有不同的身份哈希码。

【讨论】:

  • 您还没有解释为什么s5 具有不同的身份哈希码而s3 没有。现在,不要写给我,因为我知道,请更新您的答案,以便 OP 可以阅读它。
  • @Tom 更新按照建议进行 - 如果我有任何误解,请告诉我。
  • 谢谢@Romski ...我认为,没有像字符串池这样的专用区域。所有对象都是在堆上创建的。但是肯定有字符串池的概念,这将有助于实现预期的行为。我遇到了来自 javaranch 的链接,将其发布为对此的答案。 ...非常感谢您的帮助:)
【解决方案2】:

我进行了更多搜索,发现了一个来自 javaranch 的链接,该链接指出了围绕创建 String 对象的普遍困惑。我还修改了我的程序以验证文章中的声明。这是链接:-

http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html

这样做:-

  1. 所有对象总是在堆上创建。字符串对象不是 例外。
  2. 字符串池或表更像是查找,检查对象是否需要 为文字常量(不是新的)创建...如果是,则创建 它在堆上并记下它在池或表中的引用。
  3. 如果具有相同值的字符串对象已经存在并且引用 它存在于表或字符串池中...使用相同的引用 (在我们的示例中为 s1、s2、s3)
  4. 如果要使用new创建String对象,不需要查找,只需 去创建一个新对象并使用这个新引用
  5. 如果有人在此对象上调用“实习生”(根据 (4) 创建)... 然后在表中查找...并返回匹配字符串的引用 字面意思。
  6. 如果使局部变量引用 null,则字符串字面量 常量仍然继续被表或字符串池引用, 因此永远不会收集垃圾。

但是 NO SPECIAL AREA 称为 STRING POOL,其中创建了字符串字面量常量。这是我从那个链接中得到的。如果我错了,请纠正我。

我通过在程序中添加以下行来验证 6. 点:-

s1 = s2 = s3 = s5 = s6 = null;
System.gc();
try {
    Thread.sleep(10000);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
System.gc();
System.out.println("\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
System.out.println("String literal pool's available or not ?");
System.out.println("Omkar Patkar".hashCode());
System.out.println(System.identityHashCode("Omkar Patkar"));

它们给出相同的哈希码和身份哈希码。

Hashcode s1 = 2062602683
Hashcode s2 = 2062602683
Hashcode s3 = 2062602683
Hashcode s4 = 76311326
Hashcode s5 = 2062602683
Hashcode s5.intern() = 2062602683
Hashcode s6 = 2062602683
Hashcode s6.intern() = 2062602683
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Indentity Hashcode s1 = 20732290
Indentity Hashcode s2 = 20732290
Indentity Hashcode s3 = 20732290
Indentity Hashcode s4 = 18378667
Indentity Hashcode s5 = 21722195
Indentity Hashcode s6 = 12719253
Indentity Hashcode intern s6 = 20732290
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

String literal pool's available or not ?
2062602683
20732290

【讨论】:

    猜你喜欢
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-14
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多