对String很少有疑问,
我在某些陈述中可能出错,因为我根据我对互联网上各种文章的理解来写这个,请耐心等待。
当我们这样做的时候 String str1 = new String(“newStr1”); 。 这将创建2个字符串对象。一个在常规堆中,另一个在字符串池中。为什么2个物体及其用途?为什么不在游泳池上呢?
如果我们将对象创建为 String str2 = new String(“newStr2”)。intern(); 。 这将检查池中是否存在类似(有意义的相等)对象,并对其进行引用。如果没有,它会在池中创建一个但不在堆中创建吗?如果是这样,我们应该在大多数时间使用实习生来节省记忆?虽然它会影响性能。 所以基本上它是 String str2 =“newStr2”; (对于字符串文字隐含实习)
在Java-6之后,字符串池从perm gen空间移动到堆区域?所以基本上我们现在只有一个区域作为堆,或者字符串池现在作为堆中的单独部分?如果它不是一个单独的部分,那么仍然会创建2个对象?
答案 0 :(得分:2)
认为字符串池是存储字符串的特殊位置。您可以认为字符串池也在堆中(实际上就是我所知道的),只需要小心处理池中每个值只有一个副本,这样可以轻松地重用相同的实例(例如,当你声明一个字符串文字时)
因为被告知要这样做。 "newStr1"
是一个字符串文字,它将在池中创建/查找。 String str1 = new String (...)
您告诉JVM创建一个String对象的新实例。所以它只是遵循你告诉它要做的事情。当然JIT可以优化它以避免创建新实例(现在它正在进行这种优化吗?)但是你所描述的行为就是JVM告诉你做的事情。
它与上述相同。但是,在new String(...)
(创建一个新的String对象)之后,您调用了intern()
,因此在字符串池中进行查找。同样,这种行为就是被告知要做的事情。是的,你是对的,在你的情况下,结果与String str1="asdf";
完全相同,并完成了一些不必要的工作。但是,在某些情况下,构造函数不会使用String文字,并且您仍希望将String强制实施为字符串池。在这种情况下,intern()
将变得有意义。
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/链接。