Java的String.intern()的目的是什么?

时间:2014-03-18 07:45:23

标签: java string

我知道有两种方法可以在Java中创建String:

String a = "aaa";
String b = new String("bbb");

首先,Java肯定会在字符串池中创建一个String对象,并使a引用它。 (假设“aaa”之前不在游泳池里。)

使用第二种方法,将在堆中创建一个对象,但是jvm还会在字符串池中创建一个对象吗?

在这篇文章Questions about Java's String pool中,@ Jesper说:

  

如果你这样做:

String s = new String("abc");
     

然后池中将有一个String对象,代表文字“abc”,>并且将有一个单独的String对象,而不是在池中,它包含>的副本。合并对象的内容。

如果这是真的,那么每次使用new String("bbb");时,在池中创建一个对象“bbb”,这意味着通过上面的任何一种方式,java将始终在池中创建一个字符串对象。那么intern()用于什么?在文档http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern()中,它说:

  

当调用intern方法时,如果池已经包含一个等于此String对象的字符串(由equals(Object)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回对此String对象的引用。

这意味着有些字符串不在池中,可能吗?哪一个是真的?

4 个答案:

答案 0 :(得分:9)

如您所知,Java编程语言中的不可变对象中的String,这意味着一旦构造就无法更改。因此,JVM能够维护文字池,这有助于减少内存使用并提高性能。每次使用String文字时,JVM都会检查文字池,如果文字已经可用,则会返回相同的引用。如果不是,则会在文字池中创建并添加新的String对象。

当您尝试创建类似基元或文字/常量的String时,会应用此理论。

String str = "bbb";

但是当你创建一个新的String对象

String str = new String("bbb");

重写上述规则并始终创建新实例。

但即使您使用intern创建StringString类中的literal API也可用于从String池中选择new引用str3运营商。请查看以下给出的示例。尽管new是使用intern运算符创建的,因为我们使用了literal方法,JVM从public class StringInternExample { public static void main(final String args[]) { final String str = "bbb"; final String str1 = "bbb"; final String str2 = new String("bbb"); final String str3 = new String("bbb").intern(); System.out.println("str == str1 : "+(str == str1)); System.out.println("str == str2 : "+(str == str2)); System.out.println("str == str3 : "+(str == str3)); } } 池中获取了引用。

str == str1 : true
str == str2 : false
str == str3 : true

输出上述代码:

{{1}}

您可以查看:Confusion on string immutability

答案来源:http://ourownjava.com/java/java-string-immutability-and-intern-method/

Shishir

答案 1 :(得分:4)

我们的String对象基本上可以通过两种方式进入池中:

  • "bbb"等源代码中使用文字。
  • 使用intern

intern适用于有String的情况,而不是来自池中的String bb = "bbb".substring(1); // substring creates a new object System.out.println(bb == "bb"); // false System.out.println(bb.intern() == "bb"); // true 。例如:

System.out.println(new String("bbb").intern() == "bbb"); // true

或略有不同:

new String("bbb")

String fromLiteral = "bbb"; // in pool String fromNewString = new String(fromLiteral); // not in pool 会创建两个对象......

String

......但它更像是一个特例。它创建了两个对象,因为"bbb" refers to an object

  

字符串文字是对类String [...]的实例的引用。

     

此外,字符串文字始终引用类new String(...)的相同实例。

String会创建一份副本。

但是,有许多方法可以在不使用文字的情况下创建String个对象,例如:

  • 执行某种突变的所有substring方法。 (splitreplaceString等。)
  • 从某种输入中读取Scanner,例如Readerintern
  • 当至少一个操作数不是编译时常量时连接。

String允许您将它们添加到池中或检索现有对象(如果有)。在大多数情况下,实习==是不必要的,但它可以用作优化,因为:

  • 可让您与{{1}}进行比较。
  • 它可以节省内存,因为重复可以被垃圾收集。

答案 2 :(得分:1)

是的,new String("abc")将在内存中创建一个新对象,因此建议避免使用它。请查看Josh Bloch的Effective Java第5项“避免创建不必要的对象”,其中有更好的解释:

  

作为不做的极端例子,请考虑以下陈述:

     

String s = new String("stringette"); // DON'T DO THIS!

     

声明   每次执行时都会创建一个新的String实例,而不是   那些对象创作是必要的。 String的参数   构造函数(“stringette”)本身就是一个String实例,在功能上   与构造函数创建的所有对象相同。如果这   用法发生在循环或频繁调用的方法中,数百万   可以不必要地创建字符串实例。改进版是   只需以下内容:

     

String s = "stringette";

     

此版本使用了   单个String实例,而不是每次创建一个新实例   执行。此外,保证对象将被重用   通过在同一个虚拟机中运行的任何其他代码   包含相同的字符串文字[JLS,3.10.5]。

http://uet.vnu.edu.vn/~chauttm/e-books/java/Effective.Java.2nd.Edition.May.2008.3000th.Release.pdf

答案 3 :(得分:1)

  

使用第二种方法,将在堆中创建一个对象,但是jvm还会在字符串池中创建一个对象吗?

是的,字符串文字 "bbb",它确保了实习字符串 1 。字符串构造函数创建一个 new 字符串对象,该对象是具有相同长度和内容的副本 - 新创建的字符串自动实现。

  

如果这是真的,那么每次使用新的String(“bbb”);时,在池中创建一个对象“bbb”,这意味着通过上面的任何一种方式,java将始终在池中创建一个字符串对象。那么intern()用于什么?

仅自动实习字符串文字。必须手动实现其他字符串对象,如果这是期望的行为。

  

这意味着有些字符串不在池中,可能吗?

除了对String.intern的手动调用外,字符串文字会产生实习字符串。

虽然我建议在这种情况下使用专门的集合,但在可以用于avoid creating extra duplicate objects的情况下,实习可能很有用。实习可能有用的一些用例 - 例如,相同的字符串值可以出现多次 - 是在JSON密钥和XML元素/属性名称中。


1 这是微不足道的原因,请考虑:

String _b = "bbb";          // string from string literal (this is interned)
String b = new String(_b);  // create a NEW string via "copy constructor"
b == _b           // -> false (new did NOT return an interned string)
b.equals(_b)      // -> true  (but it did return an equivalent string)
b.intern() == _b  // -> true  (which interns to .. the same string object)