池和堆中的字符串创建

时间:2015-11-12 03:06:56

标签: java string string-interning

对String很少有疑问,

我在某些陈述中可能出错,因为我根据我对互联网上各种文章的理解来写这个,请耐心等待。

  1. 当我们这样做的时候 String str1 = new String(“newStr1”); 。 这将创建2个字符串对象。一个在常规堆中,另一个在字符串池中。为什么2个物体及其用途?为什么不在游泳池上呢?

  2. 如果我们将对象创建为 String str2 = new String(“newStr2”)。intern(); 。 这将检查池中是否存在类似(有意义的相等)对象,并对其进行引用。如果没有,它会在池中创建一个但不在堆中创建吗?如果是这样,我们应该在大多数时间使用实习生来节省记忆?虽然它会影响性能。 所以基本上它是 String str2 =“newStr2”; (对于字符串文字隐含实习)

  3. 在Java-6之后,字符串池从perm gen空间移动到堆区域?所以基本上我们现在只有一个区域作为堆,或者字符串池现在作为堆中的单独部分?如果它不是一个单独的部分,那么仍然会创建2个对象?

2 个答案:

答案 0 :(得分:2)

认为字符串池是存储字符串的特殊位置。您可以认为字符串池也在堆中(实际上就是我所知道的),只需要小心处理池中每个值只有一个副本,这样可以轻松地重用相同的实例(例如,当你声明一个字符串文字时)

  1. 因为被告知要这样做。 "newStr1"是一个字符串文字,它将在池中创建/查找。 String str1 = new String (...)您告诉JVM创建一个String对象的新实例。所以它只是遵循你告诉它要做的事情。当然JIT可以优化它以避免创建新实例(现在它正在进行这种优化吗?)但是你所描述的行为就是JVM告诉你做的事情。

  2. 它与上述相同。但是,在new String(...)(创建一个新的String对象)之后,您调用了intern(),因此在字符串池中进行查找。同样,这种行为就是被告知要做的事情。是的,你是对的,在你的情况下,结果与String str1="asdf";完全相同,并完成了一些不必要的工作。但是,在某些情况下,构造函数不会使用String文字,并且您仍希望将String强制实施为字符串池。在这种情况下,intern()将变得有意义。

  3. Perm Gen IS 堆区域的一部分。 (Sun / Oracle pre-8)JVM将堆分成不同的代并移动对象,这会影响对象的GC编辑方式。 PermGen只是堆中从未得到GC-ed的部分。但是,它仍然是堆的一部分。因此,PermGen与GC算法更相关,您可能会注意到,JDK8中没有PermGen。

答案 1 :(得分:1)

在Java中,如果JVM识别文字(&#34; xyz&#34;),它将立即在String常量池中创建一个对象,同时如果它识别 new < / strong>然后它将在heap.now中创建一个对象前进到查询:

1.String str1 = new String(&#34; newStr1&#34;); 这里是JVM&#34; newStr1&#34;是文字的,因此它将遵循与文字对应的规则,因此它在String常量池中创建一个对象。 new String(&#34; newStr1&#34;) - 这里对于new运算符,它遵循与new运算符对应的规则,因此它也将在堆中创建一个对象。

2.intern():这里的实习生不会在pool.interno中创建一个对象,用于更改字符串对象以引用字符串池而不是堆。 string s1 = new String(&#34; newStr1&#34;) - 这里s1将指向堆区域而不是字符串常量池。 String s1 = new String(&#34; newStr1&#34;)。intern()会使s1指向字符串常量池,因为 newStr1 是在堆和字符串常量池中创建的。 intern()不会处理字符串对象的创建。

3.permgen:为了使有效的垃圾收集堆分为不同的区域,其中permgen也是一个区域,它仍然只在堆内,它是堆内的一个区域。请参考这个堆区域的http://www.cubrid.org/blog/dev-platform/understanding-java-garbage-collection/链接。