1

我对该intern()方法的有用性有些困惑。

这行代码可以消除我的困惑:

String a = new String("abc").intern();

上面这行代码会创建多少个对象?如果它将在堆内存和字符串池内存中创建一个对象,那么该intern()方法如何提高性能?

4

2 回答 2

2

上面这行代码会创建多少个对象?

  • 字符串文字在运行时由一个String对象表示。如果该对象尚未创建,则可以通过执行此语句(延迟地)创建它。在任何一种情况下,表示文字的对象都将被实习。(String在此过程中创建的对象数量是取决于 Java 版本的实现细节。是的,真的。)

  • new String(...)每次执行时都会创建一个对象。

  • 由于原始对象String 已被实习,因此intern()调用将返回该对象;即String代表字符串文字的那个:你开始的那个。

因此,总而言之,您的代码可能会直接在幕后创建最多三个对象,但在new语句结束时将无法访问由创建的对象。

确实,因为,

String a = new String("abc").intern();

String a = "abc";

给出相同的结果,new/intern序列完全是浪费时间。


如果它将在堆内存和字符串池内存中创建一个对象,那么 intern() 方法如何提高性能?

不会直接提高性能:

  • 如果您可以实习数据结构中的所有字符串,则有潜在的间接好处。然后你可以使用==而不是equals(Object)测试是否相等。

    但是,您在权衡成本equals与成本intern,因此在获得净性能胜利之前,您需要进行一些对象比较。此外,如果您忘记实习其中一个字符串,==可能会给您一个不同的答案equals。(这可能是一个错误!)

  • 在较旧的 JVM 中,如果您有很多长生命周期的String对象,则会有潜在的间接好处。使用internto de-dup 将减少长期内存使用并降低长期 GC 成本。

    然而,在最近的 JVM 中,GC 将自动删除String在几个 GC 周期中存活的对象。由于这适用于相对长寿命的对象,因此这是一种更有效的去重方法。并且该过程对应用程序是透明的!

简而言之,在大多数情况下,intern()在应用程序代码中使用该方法没有优点和明显的缺点。不要管它。

于 2019-05-07T10:42:25.493 回答
1

您将有两个字符串:

  • "abc"- 字符串文字。它还将“abc”添加到字符串池中(见下文)
  • new String("abc")- 使用 new 运算符显式创建的“abc”的新副本

请注意,调用 intern 时不会发生任何事情,因为"abc"自从声明字符串文字以来,字符串已经存在于字符串池中。

此外,分配不会创建任何新对象。

方法intern

返回字符串对象的规范表示。一个字符串池,最初是空的,由 String 类私下维护。当调用 intern 方法时,如果池中已经包含一个等于该 String 对象的字符串,由 equals(Object) 方法确定,则返回池中的字符串。否则,将此 String 对象添加到池中并返回对该 String 对象的引用。由此可见,对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为真时,s.intern() == t.intern() 才为真。 所有文字字符串和字符串值常量表达式都是 interned。字符串文字在 Java™ 语言规范的第 3.10.5 节中定义。

在这种情况下,对实习生的调用没有任何用处,因此您的表现不会有任何提高。

于 2019-05-07T10:25:24.737 回答