如何存储使用new()但在Java中作为文字创建的重复字符串?

时间:2017-05-07 08:25:45

标签: java

String Str1= new String("java");  
String Str3 = new String("java");

System.out.println(Str1==Str3);

第一行代码在str1池和堆中创建内容为"java" init的对象String。现在Str3会做什么?我知道它在堆中创建Str3什么关于字符串池中的Str3?第3行做什么?它检查String池或堆区域中的相等性吗?我知道它给出了错误,但我的问题是,如果Str1和Str3存储在字符串池==应该给出正确的,因为引用是相同的。

1 个答案:

答案 0 :(得分:2)

  

第一行代码在String池和堆中创建带有内容“java”init的对象str1。

实际上:

  1. 字符串池是堆的一部分。 (这实际上并不涉及你的误解,但它有助于让这些事情直截了当。)
  2. 对应于“java”文字的字符串对象由类加载器创建,而不是由该语句创建。它是在加载类时创建的 1 ...而不是代码运行时。
  3. 因此,实际上语句 only 会在堆中创建一个字符串对象。

      

    现在Str3会做什么?

    第二个语句在堆中创建一个字符串对象....

    根据上面的解释,此语句中使用的“java”文字的字符串对象是先前创建的。 (实际上,如果查看字节码文件,您会发现文件的常量池中只有一个“java”字符串。因此,类加载器甚至不需要创建两个字符串实例和intern()他们只创造了一个并实习。)

      

    我知道它在堆中创建Str3在字符串池中的Str3怎么样?

    不。所有字符串文字都在字符串池中创建,它会自动扣除它们。

      

    第3行做什么?它是检查字符串池还是堆区域中的相等性?

    不。它测试以查看对象引用是否相同;即如果它们是同一个物体。它实际上并没有测试它们的位置。

    (你实际上无法直接测试String是否在池中。你甚至无法测试对象是否在堆中......如果JVM为你提供了一种分配对象的方法在(常规)堆之外。)

      

    我知道它给出了错误,但我的问题是,如果Str1和Str3存储在String pool中==应该为true,因为引用是相同的。

    它们不在字符串池中。它们是普通的堆对象。

    以这种方式思考,==返回false 的事实证明它们不是(两者)在字符串池中。因为如果它们都在字符串池中,则它们必须相同的String对象。

    以下是JLS对字符串文字和标识的说法:

      

    “此外,字符串文字总是引用类String的相同实例。这是因为字符串文字 - 或者更一般地说,作为常量表达式的值的字符串(第15.28节) - 是”实习“以便使用String.intern方法分享唯一的实例。”

    当班级加载 1 时会发生这种实习。

    1 - 规格没有说实习发生的时间。看来最近的JVM懒惰地解析了方法对String文字的引用;即,在字节码解释器第一次调用该方法时发生实习。但是,这并没有改变上述解释的实质内容。