0

对字符串有一些疑问,

我根据网上各种文章的理解写这篇文章,有些说法可能有误,请多多包涵。

  1. 当我们做 String str1 = new String ("newStr1"); . 这将创建 2 个字符串对象。一个在常规堆中,另一个在字符串池中。为什么 2 个对象及其用法?为什么不只是一个在游泳池?

  2. 如果我们将对象创建为String str2 = new String("newStr2").intern(); . 这将检查池中是否存在类似(有意义相等)的对象,并提供对它的引用。如果没有,它会在池中创建一个,而不是在堆中?如果是这样,那么我们应该大部分时间使用实习生来节省内存吗?尽管它会稍微影响性能。所以基本上它是String str2 = "newStr2"; (对于字符串文字来说,interning 是隐式的)

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

4

2 回答 2

3

在 java 中,如果 JVM 识别出字面量(“xyz”),它将立即在字符串常量池中创建一个对象,同时如果它识别出new则它将在 heap.now 中创建一个对象,然后继续查询:

1.String str1 = new String ("newStr1") ; 这里对于 JVM "newStr1" 是字面量,所以它会遵循与字面量相对应的规则,所以它在字符串常量池中创建一个对象。new String("newStr1")——这里对于new操作符,它遵循new操作符对应的规则,所以它也会在堆中创建一个对象。

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

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

于 2015-11-12T09:06:35.337 回答
2

试想一下,字符串池是一个存储字符串的特殊地方。您可以考虑字符串池也在堆中(据我所知,它实际上是),只是池被小心处理,其中每个值只有一个副本,因此可以轻松重用同一个实例(例如,当您声明一个字符串文字时)

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

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

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

于 2015-11-12T03:22:58.587 回答