如何使用Java创建和存储字符串?

时间:2015-06-14 08:56:39

标签: java string memory-management immutability hashcode

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

predictedLabels = predict(classifier, testFeatures);

我看到以下输出: -

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()));


    }

}

s5和s6的身份哈希码与s1,s2,s3不同......为什么会这样?

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

2 个答案:

答案 0 :(得分:1)

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

使用new关键字创建的字符串对象会导致存储在堆上的对象。它们的处理方式与任何其他对象相同。创建具有相同String值的2个对象将导致2个对象各自拥有它自己的引用。使用new与String池中的String文字效率不同。实例化String对象会将其移动到String池。

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

修改

从2个字符串文字的串联创建的字符串将产生字符串文字,例如s3。因此,s3具有与s1和s2相同的标识哈希码。但是,s5是从String文本和引用创建到String文本,从而生成一个新对象。这解释了为什么它具有不同的身份哈希码。

答案 1 :(得分:0)

我进行了更多搜索并遇到了来自javaranch的链接,该链接指出了围绕String对象创建的一般混淆。我还修改了我的程序以验证文章中的声明。这是链接: -

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

顺便说一下: -

  1. 始终在堆上创建所有对象。字符串对象没有 例外。
  2. 字符串池或表更像是查找,以检查对象是否需要 为文字常量(不是新的)创建...如果是,则创建 它在堆上,并在池或表中记下它的引用。
  3. 如果已存在具有相同值的String对象并且引用了 它存在于表或字符串池中......使用相同的引用 (在我们的例子中,s1,s2,s3)
  4. 如果要使用new创建String对象,则不需要查找 去创建一个新对象并使用这个新的参考
  5. 如果有人在此对象上调用“实习生”(按照(4)创建)... 然后在表中查找...并返回匹配String的引用 文字。
  6. 如果使局部变量引用null,则为String literal 常量仍然继续由表或字符串池引用, 因此从不垃圾收集。
  7. 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"));
    

    并且它们提供相同的哈希码和identityhashcode。

    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